arduino_ci 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  #include "Godmode.h"
2
2
  #include "HardwareSerial.h"
3
+ #include "SPI.h"
3
4
 
4
5
  GodmodeState godmode = GodmodeState();
5
6
 
@@ -67,6 +68,16 @@ int analogRead(unsigned char pin) {
67
68
  return godmode->analogPin[pin].retrieve();
68
69
  }
69
70
 
71
+ void attachInterrupt(uint8_t interrupt, void ISR(void), uint8_t mode) {
72
+ GodmodeState* godmode = GODMODE();
73
+ godmode->interrupt[interrupt].attached = true;
74
+ godmode->interrupt[interrupt].mode = mode;
75
+ }
76
+
77
+ void detachInterrupt(uint8_t interrupt) {
78
+ GodmodeState* godmode = GODMODE();
79
+ godmode->interrupt[interrupt].attached = false;
80
+ }
70
81
 
71
82
  // Serial ports
72
83
  #if defined(HAVE_HWSERIAL0)
@@ -87,3 +98,6 @@ inline std::ostream& operator << ( std::ostream& out, const PinHistory<T>& ph )
87
98
  out << ph;
88
99
  return out;
89
100
  }
101
+
102
+ // defined in SPI.h
103
+ SPIClass SPI = SPIClass(&godmode.spi.dataIn, &godmode.spi.dataOut);
@@ -2,7 +2,6 @@
2
2
  #include "ArduinoDefines.h"
3
3
  #include <avr/io.h>
4
4
  #include "WString.h"
5
- #include "ci/Queue.h"
6
5
  #include "PinHistory.h"
7
6
 
8
7
  // random
@@ -39,8 +38,9 @@ class GodmodeState {
39
38
  unsigned long readDelayMicros;
40
39
  };
41
40
 
42
- struct ToneDef {
43
-
41
+ struct InterruptDef {
42
+ bool attached;
43
+ uint8_t mode;
44
44
  };
45
45
 
46
46
  public:
@@ -50,6 +50,8 @@ class GodmodeState {
50
50
  PinHistory<bool> digitalPin[MOCK_PINS_COUNT];
51
51
  PinHistory<int> analogPin[MOCK_PINS_COUNT];
52
52
  struct PortDef serialPort[NUM_SERIAL_PORTS];
53
+ struct InterruptDef interrupt[MOCK_PINS_COUNT]; // not sure how to get actual number
54
+ struct PortDef spi;
53
55
 
54
56
  void resetPins() {
55
57
  for (int i = 0; i < MOCK_PINS_COUNT; ++i) {
@@ -62,9 +64,33 @@ class GodmodeState {
62
64
  micros = 0;
63
65
  }
64
66
 
67
+ void resetInterrupts() {
68
+ for (int i = 0; i < MOCK_PINS_COUNT; ++i) {
69
+ interrupt[i].attached = false;
70
+ }
71
+ }
72
+
73
+ void resetPorts() {
74
+ for (int i = 0; i < serialPorts(); ++i)
75
+ {
76
+ serialPort[i].dataIn = "";
77
+ serialPort[i].dataOut = "";
78
+ serialPort[i].readDelayMicros = 0;
79
+ }
80
+ }
81
+
82
+ void resetSPI() {
83
+ spi.dataIn = "";
84
+ spi.dataOut = "";
85
+ spi.readDelayMicros = 0;
86
+ }
87
+
65
88
  void reset() {
66
89
  resetClock();
67
90
  resetPins();
91
+ resetInterrupts();
92
+ resetPorts();
93
+ resetSPI();
68
94
  seed = 1;
69
95
  }
70
96
 
@@ -75,14 +101,7 @@ class GodmodeState {
75
101
  GodmodeState()
76
102
  {
77
103
  reset();
78
- for (int i = 0; i < serialPorts(); ++i)
79
- {
80
- serialPort[i].dataIn = "";
81
- serialPort[i].dataOut = "";
82
- serialPort[i].readDelayMicros = 0;
83
- }
84
- }
85
-
104
+ }
86
105
  };
87
106
 
88
107
  // io pins
@@ -95,10 +114,11 @@ int analogRead(uint8_t);
95
114
  void analogWrite(uint8_t, int);
96
115
  #define analogReadResolution(...) _NOP()
97
116
  #define analogWriteResolution(...) _NOP()
117
+ void attachInterrupt(uint8_t interrupt, void ISR(void), uint8_t mode);
118
+ void detachInterrupt(uint8_t interrupt);
98
119
 
99
120
  // TODO: issue #26 to track the commanded state here
100
121
  inline void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0) {}
101
- inline void tone(uint8_t _pin, unsigned int frequency) {}
102
122
  inline void noTone(uint8_t _pin) {}
103
123
 
104
124
 
@@ -0,0 +1,150 @@
1
+ #pragma once
2
+
3
+ #include "Stream.h"
4
+
5
+ // defines from original file
6
+ #define _SPI_H_INCLUDED
7
+ #define SPI_HAS_TRANSACTION 1
8
+ #define SPI_HAS_NOTUSINGINTERRUPT 1
9
+ #define SPI_ATOMIC_VERSION 1
10
+ #define SPI_CLOCK_DIV4 0x00
11
+ #define SPI_CLOCK_DIV16 0x01
12
+ #define SPI_CLOCK_DIV64 0x02
13
+ #define SPI_CLOCK_DIV128 0x03
14
+ #define SPI_CLOCK_DIV2 0x04
15
+ #define SPI_CLOCK_DIV8 0x05
16
+ #define SPI_CLOCK_DIV32 0x06
17
+ #define SPI_MODE0 0x00
18
+ #define SPI_MODE1 0x04
19
+ #define SPI_MODE2 0x08
20
+ #define SPI_MODE3 0x0C
21
+ #define SPI_MODE_MASK 0x0C
22
+ #define SPI_CLOCK_MASK 0x03
23
+ #define SPI_2XCLOCK_MASK 0x01
24
+
25
+ #ifndef LSBFIRST
26
+ #define LSBFIRST 0
27
+ #endif
28
+ #ifndef MSBFIRST
29
+ #define MSBFIRST 1
30
+ #endif
31
+
32
+ #if defined(EIMSK)
33
+ #define SPI_AVR_EIMSK EIMSK
34
+ #elif defined(GICR)
35
+ #define SPI_AVR_EIMSK GICR
36
+ #elif defined(GIMSK)
37
+ #define SPI_AVR_EIMSK GIMSK
38
+ #endif
39
+
40
+
41
+ class SPISettings {
42
+ public:
43
+ SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode){};
44
+ SPISettings(){};
45
+ };
46
+
47
+
48
+ class SPIClass: public ObservableDataStream {
49
+ public:
50
+
51
+ SPIClass(String* dataIn, String* dataOut) {
52
+ this->dataIn = dataIn;
53
+ this->dataOut = dataOut;
54
+ }
55
+
56
+ // Initialize the SPI library
57
+ void begin() { isStarted = true; }
58
+
59
+ // Disable the SPI bus
60
+ void end() { isStarted = false; }
61
+
62
+ // this has no tangible effect in a mocked Arduino
63
+ void usingInterrupt(uint8_t interruptNumber){}
64
+ void notUsingInterrupt(uint8_t interruptNumber){}
65
+
66
+ // Before using SPI.transfer() or asserting chip select pins,
67
+ // this function is used to gain exclusive access to the SPI bus
68
+ // and configure the correct settings.
69
+ void beginTransaction(SPISettings settings)
70
+ {
71
+ #ifdef SPI_TRANSACTION_MISMATCH_LED
72
+ if (inTransactionFlag) {
73
+ pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
74
+ digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
75
+ }
76
+ inTransactionFlag = 1;
77
+ #endif
78
+ }
79
+
80
+ // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
81
+ uint8_t transfer(uint8_t data) {
82
+ //FIXME!
83
+ // push memory->bus
84
+ dataOut->append(String((char)data));
85
+ advertiseByte((char)data);
86
+
87
+ // pop bus->memory data from its queue and return it
88
+ if (dataIn->empty()) return 0;
89
+ char ret = (*dataIn)[0];
90
+ *dataIn = dataIn->substr(1, dataIn->length());
91
+ return ret;
92
+ }
93
+
94
+ uint16_t transfer16(uint16_t data) {
95
+ union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out;
96
+ in.val = data;
97
+ if (!(SPCR & (1 << DORD))) {
98
+ out.msb = transfer(in.msb);
99
+ out.lsb = transfer(in.lsb);
100
+ } else {
101
+ out.lsb = transfer(in.lsb);
102
+ out.msb = transfer(in.msb);
103
+ }
104
+ return out.val;
105
+ }
106
+
107
+ void transfer(void *buf, size_t count) {
108
+ // TODO: this logic is rewritten from the original,
109
+ // I'm not sure what role the SPDR register (which I removed) plays
110
+
111
+ uint8_t *p = (uint8_t *)buf;
112
+ for (int i = 0; i < count; ++i) {
113
+ *(p + i) = transfer(*(p + i));
114
+ }
115
+ }
116
+
117
+ // After performing a group of transfers and releasing the chip select
118
+ // signal, this function allows others to access the SPI bus
119
+ void endTransaction(void) {
120
+ #ifdef SPI_TRANSACTION_MISMATCH_LED
121
+ if (!inTransactionFlag) {
122
+ pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
123
+ digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
124
+ }
125
+ inTransactionFlag = 0;
126
+ #endif
127
+ }
128
+
129
+ // deprecated functions, skip 'em
130
+ void setBitOrder(uint8_t bitOrder){}
131
+ void setDataMode(uint8_t dataMode){}
132
+ void setClockDivider(uint8_t clockDiv){}
133
+ void attachInterrupt(){}
134
+ void detachInterrupt(){}
135
+
136
+ private:
137
+ uint8_t initialized; // initialized in Godmode.cpp
138
+ uint8_t interruptMode; // 0=none, 1=mask, 2=global
139
+ uint8_t interruptMask; // which interrupts to mask
140
+ uint8_t interruptSave; // temp storage, to restore state
141
+ #ifdef SPI_TRANSACTION_MISMATCH_LED
142
+ uint8_t inTransactionFlag;
143
+ #endif
144
+
145
+ bool isStarted = false;
146
+ String* dataIn;
147
+ String* dataOut;
148
+ };
149
+
150
+ extern SPIClass SPI;
@@ -27,6 +27,13 @@ class ArduinoCITable {
27
27
  public:
28
28
  ArduinoCITable() : mNilK(), mNilV() { init(); }
29
29
 
30
+ ArduinoCITable(const ArduinoCITable& obj) : mNilK(), mNilV() {
31
+ init();
32
+ for (Node* p = obj.mStart; p; p = p->next) {
33
+ add(p->key, p->val);
34
+ }
35
+ }
36
+
30
37
  // number of things in the table
31
38
  inline unsigned long size() const { return mSize; }
32
39
 
@@ -119,6 +126,7 @@ class ArduinoCITable {
119
126
  mStart = mStart->next;
120
127
  delete p;
121
128
  }
129
+ mSize = 0;
122
130
  }
123
131
 
124
132
  ~ArduinoCITable() { clear(); }
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'arduino_ci'
3
3
  require 'set'
4
+ require 'pathname'
4
5
 
5
6
  WIDTH = 80
6
7
 
7
8
  @failure_count = 0
9
+ @passfail = proc { |result| result ? "✓" : "✗" }
8
10
 
9
11
  # terminate after printing any debug info. TODO: capture debug info
10
12
  def terminate(final = nil)
@@ -21,7 +23,7 @@ def terminate(final = nil)
21
23
  end
22
24
 
23
25
  # make a nice status line for an action and react to the action
24
- def perform_action(message, multiline, on_fail_msg, abort_on_fail)
26
+ def perform_action(message, multiline, mark_fn, on_fail_msg, abort_on_fail)
25
27
  line = "#{message}... "
26
28
  endline = "...#{message} "
27
29
  if multiline
@@ -29,8 +31,9 @@ def perform_action(message, multiline, on_fail_msg, abort_on_fail)
29
31
  else
30
32
  print line
31
33
  end
34
+ STDOUT.flush
32
35
  result = yield
33
- mark = result ? "" : "✗"
36
+ mark = mark_fn.nil? ? "" : mark_fn.call(result)
34
37
  # if multline, put checkmark at full width
35
38
  print endline if multiline
36
39
  puts mark.rjust(WIDTH - line.length, " ")
@@ -45,17 +48,38 @@ end
45
48
 
46
49
  # Make a nice status for something that defers any failure code until script exit
47
50
  def attempt(message, &block)
48
- perform_action(message, false, nil, false, &block)
51
+ perform_action(message, false, @passfail, nil, false, &block)
49
52
  end
50
53
 
51
54
  # Make a nice status for something that defers any failure code until script exit
52
55
  def attempt_multiline(message, &block)
53
- perform_action(message, true, nil, false, &block)
56
+ perform_action(message, true, @passfail, nil, false, &block)
54
57
  end
55
58
 
56
59
  # Make a nice status for something that kills the script immediately on failure
57
60
  def assure(message, &block)
58
- perform_action(message, false, "This may indicate a problem with ArduinoCI!", true, &block)
61
+ perform_action(message, false, @passfail, "This may indicate a problem with ArduinoCI, or your configuration", true, &block)
62
+ end
63
+
64
+ def assure_multiline(message, &block)
65
+ perform_action(message, true, @passfail, "This may indicate a problem with ArduinoCI, or your configuration", true, &block)
66
+ end
67
+
68
+ def inform(message, &block)
69
+ perform_action(message, false, proc { |x| x }, nil, false, &block)
70
+ end
71
+
72
+ def inform_multiline(message, &block)
73
+ perform_action(message, true, nil, nil, false, &block)
74
+ end
75
+
76
+ # Assure that a platform exists and return its definition
77
+ def assured_platform(purpose, name, config)
78
+ platform_definition = config.platform_definition(name)
79
+ assure("Requested #{purpose} platform '#{name}' is defined in 'platforms' YML") do
80
+ !platform_definition.nil?
81
+ end
82
+ platform_definition
59
83
  end
60
84
 
61
85
  # initialize command and config
@@ -63,10 +87,23 @@ config = ArduinoCI::CIConfig.default.from_project_library
63
87
  @arduino_cmd = ArduinoCI::ArduinoInstallation.autolocate!
64
88
 
65
89
  # initialize library under test
66
- installed_library_path = assure("Installing library under test") { @arduino_cmd.install_local_library(".") }
90
+ installed_library_path = attempt("Installing library under test") do
91
+ @arduino_cmd.install_local_library(Pathname.new("."))
92
+ end
93
+ if installed_library_path.exist?
94
+ inform("Library installed at") { installed_library_path.to_s }
95
+ else
96
+ assure_multiline("Library installed successfully") do
97
+ @arduino_cmd.lib_dir.ascend do |path_part|
98
+ next unless path_part.exist?
99
+
100
+ break puts path_part.find.to_a.to_s
101
+ end
102
+ false
103
+ end
104
+ end
67
105
  library_examples = @arduino_cmd.library_examples(installed_library_path)
68
- cpp_library = ArduinoCI::CppLibrary.new(installed_library_path)
69
- attempt("Library installed at #{installed_library_path}") { true }
106
+ cpp_library = ArduinoCI::CppLibrary.new(installed_library_path, @arduino_cmd.lib_dir)
70
107
 
71
108
  # check GCC
72
109
  compilers = config.compilers_to_use
@@ -75,6 +112,7 @@ compilers.each do |gcc_binary|
75
112
  attempt_multiline("Checking #{gcc_binary} version") do
76
113
  version = cpp_library.gcc_version(gcc_binary)
77
114
  next nil unless version
115
+
78
116
  puts version.split("\n").map { |l| " #{l}" }.join("\n")
79
117
  version
80
118
  end
@@ -85,10 +123,11 @@ end
85
123
  # while we're doing that, get the aux libraries as well
86
124
  all_platforms = {}
87
125
  aux_libraries = Set.new(config.aux_libraries_for_unittest + config.aux_libraries_for_build)
88
- config.platforms_to_unittest.each { |p| all_platforms[p] = config.platform_definition(p) }
126
+ # while collecting the platforms, ensure they're defined
127
+ config.platforms_to_unittest.each { |p| all_platforms[p] = assured_platform("unittest", p, config) }
89
128
  library_examples.each do |path|
90
129
  ovr_config = config.from_example(path)
91
- ovr_config.platforms_to_build.each { |p| all_platforms[p] = config.platform_definition(p) }
130
+ ovr_config.platforms_to_build.each { |p| all_platforms[p] = assured_platform("library example", p, config) }
92
131
  aux_libraries.merge(ovr_config.aux_libraries_for_build)
93
132
  end
94
133
 
@@ -109,22 +148,34 @@ all_packages.each do |p|
109
148
  end
110
149
 
111
150
  aux_libraries.each do |l|
112
- assure("Installing aux library '#{l}'") { @arduino_cmd.install_library(l) }
151
+ if @arduino_cmd.library_present?(l)
152
+ inform("Using pre-existing library") { l.to_s }
153
+ else
154
+ assure("Installing aux library '#{l}'") { @arduino_cmd.install_library(l) }
155
+ end
113
156
  end
114
157
 
115
158
  # iterate boards / tests
116
159
  last_board = nil
117
- if cpp_library.test_files.empty?
118
- attempt("Skipping unit tests; no test files were found") { true }
160
+ if !cpp_library.tests_dir.exist?
161
+ inform_multiline("Skipping unit tests; no tests dir at #{cpp_library.tests_dir}") do
162
+ puts cpp_library.tests_dir.find.to_a.to_s
163
+ true
164
+ end
165
+ elsif cpp_library.test_files.empty?
166
+ inform_multiline("Skipping unit tests; no test files were found in #{cpp_library.tests_dir}") do
167
+ puts cpp_library.tests_dir.find.to_a.to_s
168
+ true
169
+ end
119
170
  elsif config.platforms_to_unittest.empty?
120
- attempt("Skipping unit tests; no platforms were requested") { true }
171
+ inform("Skipping unit tests") { "no platforms were requested" }
121
172
  else
122
173
  config.platforms_to_unittest.each do |p|
123
174
  board = all_platforms[p][:board]
124
- # assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
175
+ assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
125
176
  last_board = board
126
177
  cpp_library.test_files.each do |unittest_path|
127
- unittest_name = File.basename(unittest_path)
178
+ unittest_name = unittest_path.basename.to_s
128
179
  compilers.each do |gcc_binary|
129
180
  attempt_multiline("Unit testing #{unittest_name} with #{gcc_binary}") do
130
181
  exe = cpp_library.build_for_test_with_configuration(
@@ -147,26 +198,30 @@ else
147
198
  end
148
199
  end
149
200
 
150
- unless library_examples.empty?
201
+ if library_examples.empty?
202
+ inform_multiline("Skipping libraries; no examples found in #{installed_library_path}") do
203
+ puts installed_library_path.find.to_a.to_s
204
+ end
205
+ else
151
206
  attempt("Setting compiler warning level") { @arduino_cmd.set_pref("compiler.warning_level", "all") }
152
- end
153
207
 
154
- # unlike previous, iterate examples / boards
155
- library_examples.each do |example_path|
156
- ovr_config = config.from_example(example_path)
157
- ovr_config.platforms_to_build.each do |p|
158
- board = all_platforms[p][:board]
159
- assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
160
- last_board = board
161
- example_name = File.basename(example_path)
162
- attempt("Verifying #{example_name}") do
163
- ret = @arduino_cmd.verify_sketch(example_path)
164
- unless ret
165
- puts
166
- puts "Last command: #{@arduino_cmd.last_msg}"
167
- puts @arduino_cmd.last_err
208
+ # unlike previous, iterate examples / boards
209
+ library_examples.each do |example_path|
210
+ ovr_config = config.from_example(example_path)
211
+ ovr_config.platforms_to_build.each do |p|
212
+ board = all_platforms[p][:board]
213
+ assure("Switching to board for #{p} (#{board})") { @arduino_cmd.use_board(board) } unless last_board == board
214
+ last_board = board
215
+ example_name = File.basename(example_path)
216
+ attempt("Verifying #{example_name}") do
217
+ ret = @arduino_cmd.verify_sketch(example_path)
218
+ unless ret
219
+ puts
220
+ puts "Last command: #{@arduino_cmd.last_msg}"
221
+ puts @arduino_cmd.last_err
222
+ end
223
+ ret
168
224
  end
169
- ret
170
225
  end
171
226
  end
172
227
  end