arduino_ci 0.1.10 → 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -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