rubyduino 0.1.2 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 06e43dd1d4e9f5f4d9dbfda78f6954733999175a658f50b5d76186e6c51fc544
4
- data.tar.gz: 62a7ba189c79f9741001a6724af58026c7870aaa9da5775dcf54c824afcf53d3
3
+ metadata.gz: bac10de4fac724a35791684086ec7ac0ab440f2e3272e75d665f58a1b0d94f8d
4
+ data.tar.gz: f0c542257835047dda8edcfdd6d1c1480c27b1f2dd596f3e9e0f32303df06c81
5
5
  SHA512:
6
- metadata.gz: 9a83433f8069a0e13757f47666c6913307185d66f388eb014fa68bc54a9afd0117e4c7155bf2f8199ffa5a73c4e7de415096f8cdce2a0965f4679cd567cbf7a1
7
- data.tar.gz: deb4d7cc643e4d93c172a525677fb7944fbc6fb2bab93fe2b48f7893ca2e0886153879fedd42ee7bf06605e4dc0ac5413cb16c767bd59a0ede37cde188dbf0c4
6
+ metadata.gz: c544a3120274e0a8dc7cd53d24438c17fe4a72e6abab2c35d6130b0d1568e4f0d95d40490415fbd0a60303a89a25d9334b4f3e5f8e510b07f1046cce0193a3ac
7
+ data.tar.gz: 5ffcf8876947fa43e4d7cc9a15b6329df635230b9f397ed807cf58466e0d142e5c2ab2aa1fa1490914e848f5fc5db2e0f9d1cec54f72bd3b2468cf3b6bd636f6
data/CHANGELOG.md CHANGED
@@ -1,13 +1,25 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2026-05-08
3
+ ## [0.2.0] - 2026-05-08
4
4
 
5
- - Initial release
5
+ - Expand the ArduinoUNO API with PWM, microsecond delays, millis/micros timing, pulse measurement, serial I/O, shift helpers, and interrupt control
6
+ - Add special code generation for `serial_print` and `serial_println` so string and integer values map to the correct runtime functions
7
+ - Add an HC-SR04 ultrasonic distance sensor example
6
8
 
7
- ## [0.1.1] - 2026-05-08
9
+ ## [0.1.3] - 2026-05-08
8
10
 
9
- - Fix avrdude discovery for installed command
11
+ - Add the built-in `ArduinoUNO` prelude with FFI-backed GPIO, analog read, and millisecond delay bindings
12
+ - Replace the legacy `system("pin13:*")` sketch API with top-level helpers like `pin_mode`, `digital_write`, and `delay_ms`
13
+ - Update the default hello example to use the new ArduinoUNO API
10
14
 
11
15
  ## [0.1.2] - 2026-05-08
12
16
 
13
17
  - Update vendored Spinel revision
18
+
19
+ ## [0.1.1] - 2026-05-08
20
+
21
+ - Fix avrdude discovery for installed command
22
+
23
+ ## [0.1.0] - 2026-05-08
24
+
25
+ - Initial release
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  <div align="center">
2
2
 
3
- # Rubyduino
3
+ # Rubyduino
4
+ [Experimental]
4
5
 
5
6
  <img width="250" height="250" alt="image copy" src="https://github.com/user-attachments/assets/156c7d41-ed42-43f3-a720-ed2e9c12b52c" />
6
7
 
@@ -15,14 +16,13 @@ Under the hood it uses [Spinel](https://github.com/matz/spinel), a Ruby AOT comp
15
16
  <img width="500" height="281" alt="IMG_0197" src="https://github.com/user-attachments/assets/d2b1cc69-647a-4f63-b090-31b13a21e5a8" />
16
17
 
17
18
  ```ruby
18
- system("pin13:output")
19
+ pin_mode(ArduinoUNO::LED_BUILTIN, ArduinoUNO::OUTPUT)
19
20
 
20
21
  loop do
21
- duration = 0.1
22
- system("pin13:high")
23
- sleep duration
24
- system("pin13:low")
25
- sleep duration
22
+ digital_write(ArduinoUNO::LED_BUILTIN, ArduinoUNO::HIGH)
23
+ delay_ms(100)
24
+ digital_write(ArduinoUNO::LED_BUILTIN, ArduinoUNO::LOW)
25
+ delay_ms(100)
26
26
  end
27
27
  ```
28
28
 
data/bin/rubyduino CHANGED
@@ -98,6 +98,7 @@ rubyduino_dir = File.join(root_dir, "lib/rubyduino")
98
98
  parse_bin = File.join(spinel_dir, "spinel_parse")
99
99
  codegen_rb = File.join(rubyduino_dir, "spinel_arduino_codegen.rb")
100
100
  entry_c = File.join(rubyduino_dir, "arduino_entry.c")
101
+ arduino_uno_rb = File.join(rubyduino_dir, "arduino_uno.rb")
101
102
 
102
103
  mcu = "atmega328p"
103
104
  f_cpu = "16000000UL"
@@ -137,6 +138,7 @@ abort "rubyduino: #{source}: No such file" unless File.file?(source)
137
138
  abort "rubyduino: missing Spinel checkout at #{spinel_dir}" unless Dir.exist?(spinel_dir)
138
139
  abort "rubyduino: missing #{codegen_rb}" unless File.file?(codegen_rb)
139
140
  abort "rubyduino: missing #{entry_c}" unless File.file?(entry_c)
141
+ abort "rubyduino: missing #{arduino_uno_rb}" unless File.file?(arduino_uno_rb)
140
142
  abort "rubyduino: avr-gcc not found" unless command?("avr-gcc")
141
143
  abort "rubyduino: avr-objcopy not found" unless command?("avr-objcopy")
142
144
 
@@ -164,9 +166,11 @@ avrdude = find_avrdude
164
166
  abort "rubyduino: avrdude not found" unless avrdude
165
167
 
166
168
  ast_tmp = File.join(Dir.tmpdir, "spinel_arduino_ast.#{$PROCESS_ID}.#{rand(1_000_000)}")
169
+ source_tmp = File.join(Dir.tmpdir, "rubyduino_source.#{$PROCESS_ID}.#{rand(1_000_000)}.rb")
167
170
  begin
168
171
  warn "Spinel: #{source} -> #{c_file}"
169
- run!(parse_bin, source, ast_tmp)
172
+ File.write(source_tmp, "#{File.read(arduino_uno_rb)}\n#{File.read(source)}")
173
+ run!(parse_bin, source_tmp, ast_tmp)
170
174
  run!(RbConfig.ruby, codegen_rb, ast_tmp, c_file)
171
175
 
172
176
  warn "AVR: #{c_file} -> #{hex_file}"
@@ -183,4 +187,5 @@ begin
183
187
  run!(avrdude, *conf_args, "-p#{mcu}", "-carduino", "-P#{port}", "-b#{baud}", "-D", "-Uflash:w:#{hex_file}:i")
184
188
  ensure
185
189
  FileUtils.rm_f(ast_tmp)
190
+ FileUtils.rm_f(source_tmp)
186
191
  end
@@ -0,0 +1,39 @@
1
+ trig_pin = 9
2
+ echo_pin = 10
3
+ led_pin = 13
4
+
5
+ pin_mode(trig_pin, ArduinoUNO::OUTPUT)
6
+ pin_mode(echo_pin, ArduinoUNO::INPUT)
7
+ pin_mode(led_pin, ArduinoUNO::OUTPUT)
8
+
9
+ serial_begin(9600)
10
+
11
+ loop do
12
+ digital_write(trig_pin, ArduinoUNO::LOW)
13
+ delay_us(2)
14
+
15
+ digital_write(trig_pin, ArduinoUNO::HIGH)
16
+ delay_us(10)
17
+ digital_write(trig_pin, ArduinoUNO::LOW)
18
+
19
+ duration = pulse_in(echo_pin, ArduinoUNO::HIGH)
20
+ distance = duration * 34 / 2000
21
+
22
+ serial_print("Distance: ")
23
+ serial_print(distance)
24
+ serial_println(" cm")
25
+
26
+ blink_delay = 700
27
+
28
+ if distance < 10
29
+ blink_delay = 100
30
+ elsif distance < 30
31
+ blink_delay = 300
32
+ end
33
+
34
+ digital_write(led_pin, ArduinoUNO::HIGH)
35
+ delay_ms(blink_delay)
36
+
37
+ digital_write(led_pin, ArduinoUNO::LOW)
38
+ delay_ms(blink_delay)
39
+ end
data/examples/hello.rb CHANGED
@@ -1,9 +1,8 @@
1
- system("pin13:output")
1
+ pin_mode(ArduinoUNO::LED_BUILTIN, ArduinoUNO::OUTPUT)
2
2
 
3
3
  loop do
4
- duration = 0.1
5
- system("pin13:high")
6
- sleep duration
7
- system("pin13:low")
8
- sleep duration
4
+ digital_write(ArduinoUNO::LED_BUILTIN, ArduinoUNO::HIGH)
5
+ delay_ms(100)
6
+ digital_write(ArduinoUNO::LED_BUILTIN, ArduinoUNO::LOW)
7
+ delay_ms(100)
9
8
  end
@@ -0,0 +1,119 @@
1
+ module ArduinoUNO
2
+ LOW = 0
3
+ HIGH = 1
4
+
5
+ INPUT = 0
6
+ OUTPUT = 1
7
+ INPUT_PULLUP = 2
8
+
9
+ A0 = 14
10
+ A1 = 15
11
+ A2 = 16
12
+ A3 = 17
13
+ A4 = 18
14
+ A5 = 19
15
+
16
+ LED_BUILTIN = 13
17
+ LSBFIRST = 0
18
+ MSBFIRST = 1
19
+
20
+ ffi_func :pin_mode, [:uint8, :uint8], :int
21
+ ffi_func :digital_write, [:uint8, :uint8], :int
22
+ ffi_func :digital_read, [:uint8], :int
23
+ ffi_func :analog_read, [:uint8], :int
24
+ ffi_func :analog_write, [:uint8, :uint8], :int
25
+ ffi_func :delay_ms, [:uint32], :void
26
+ ffi_func :delay_us, [:uint32], :void
27
+ ffi_func :millis, [], :uint32
28
+ ffi_func :micros, [], :uint32
29
+ ffi_func :pulse_in, [:uint8, :uint8], :uint32
30
+ ffi_func :pulse_in_timeout, [:uint8, :uint8, :uint32], :uint32
31
+ ffi_func :serial_begin, [:uint32], :void
32
+ ffi_func :serial_available, [], :int
33
+ ffi_func :serial_read, [], :int
34
+ ffi_func :serial_write, [:uint8], :void
35
+ ffi_func :serial_print_str, [:str], :void
36
+ ffi_func :serial_print_int, [:int], :void
37
+ ffi_func :serial_println_str, [:str], :void
38
+ ffi_func :serial_println_int, [:int], :void
39
+ ffi_func :shift_in, [:uint8, :uint8, :uint8], :uint8
40
+ ffi_func :shift_out, [:uint8, :uint8, :uint8, :uint8], :void
41
+ ffi_func :interrupts, [], :void
42
+ ffi_func :no_interrupts, [], :void
43
+ end
44
+
45
+ def pin_mode(pin, mode)
46
+ ArduinoUNO.pin_mode(pin, mode)
47
+ end
48
+
49
+ def digital_write(pin, value)
50
+ ArduinoUNO.digital_write(pin, value)
51
+ end
52
+
53
+ def digital_read(pin)
54
+ ArduinoUNO.digital_read(pin)
55
+ end
56
+
57
+ def analog_read(pin)
58
+ ArduinoUNO.analog_read(pin)
59
+ end
60
+
61
+ def analog_write(pin, value)
62
+ ArduinoUNO.analog_write(pin, value)
63
+ end
64
+
65
+ def delay_ms(ms)
66
+ ArduinoUNO.delay_ms(ms)
67
+ end
68
+
69
+ def delay_us(us)
70
+ ArduinoUNO.delay_us(us)
71
+ end
72
+
73
+ def millis
74
+ ArduinoUNO.millis
75
+ end
76
+
77
+ def micros
78
+ ArduinoUNO.micros
79
+ end
80
+
81
+ def pulse_in(pin, value)
82
+ ArduinoUNO.pulse_in(pin, value)
83
+ end
84
+
85
+ def pulse_in_timeout(pin, value, timeout_us)
86
+ ArduinoUNO.pulse_in_timeout(pin, value, timeout_us)
87
+ end
88
+
89
+ def serial_begin(baud)
90
+ ArduinoUNO.serial_begin(baud)
91
+ end
92
+
93
+ def serial_available
94
+ ArduinoUNO.serial_available
95
+ end
96
+
97
+ def serial_read
98
+ ArduinoUNO.serial_read
99
+ end
100
+
101
+ def serial_write(value)
102
+ ArduinoUNO.serial_write(value)
103
+ end
104
+
105
+ def shift_in(data_pin, clock_pin, bit_order)
106
+ ArduinoUNO.shift_in(data_pin, clock_pin, bit_order)
107
+ end
108
+
109
+ def shift_out(data_pin, clock_pin, bit_order, value)
110
+ ArduinoUNO.shift_out(data_pin, clock_pin, bit_order, value)
111
+ end
112
+
113
+ def interrupts
114
+ ArduinoUNO.interrupts
115
+ end
116
+
117
+ def no_interrupts
118
+ ArduinoUNO.no_interrupts
119
+ end
@@ -3,6 +3,8 @@
3
3
 
4
4
  #include <stdint.h>
5
5
  #include <stdlib.h>
6
+ #include <string.h>
7
+ #include <avr/interrupt.h>
6
8
  #include <avr/io.h>
7
9
  #include <util/delay.h>
8
10
  #include <util/delay_basic.h>
@@ -44,8 +46,26 @@ static void sp_gc_mark(void *ptr) {
44
46
  (void)ptr;
45
47
  }
46
48
 
49
+ static inline mrb_int sp_idiv(mrb_int a, mrb_int b) {
50
+ mrb_int q;
51
+ mrb_int r;
52
+
53
+ if (b == 0) {
54
+ return 0;
55
+ }
56
+
57
+ q = a / b;
58
+ r = a % b;
59
+ if ((r != 0) && ((r ^ b) < 0)) {
60
+ q--;
61
+ }
62
+
63
+ return q;
64
+ }
65
+
47
66
  typedef struct {
48
67
  mrb_int *data;
68
+ mrb_int start;
49
69
  mrb_int len;
50
70
  mrb_int cap;
51
71
  } sp_IntArray;
@@ -69,6 +89,7 @@ static sp_Range sp_range_new(mrb_int first, mrb_int last) {
69
89
 
70
90
  static sp_IntArray *sp_IntArray_new(void) {
71
91
  sp_IntArray *array = (sp_IntArray *)malloc(sizeof(sp_IntArray));
92
+ array->start = 0;
72
93
  array->len = 0;
73
94
  array->cap = 4;
74
95
  array->data = (mrb_int *)malloc(sizeof(mrb_int) * array->cap);
@@ -80,7 +101,7 @@ static void sp_IntArray_push(sp_IntArray *array, mrb_int value) {
80
101
  array->cap *= 2;
81
102
  array->data = (mrb_int *)realloc(array->data, sizeof(mrb_int) * array->cap);
82
103
  }
83
- array->data[array->len] = value;
104
+ array->data[array->start + array->len] = value;
84
105
  array->len++;
85
106
  }
86
107
 
@@ -89,7 +110,7 @@ static mrb_int sp_IntArray_length(sp_IntArray *array) {
89
110
  }
90
111
 
91
112
  static mrb_int sp_IntArray_get(sp_IntArray *array, mrb_int index) {
92
- return array->data[index];
113
+ return array->data[array->start + index];
93
114
  }
94
115
 
95
116
  static sp_FloatArray *sp_FloatArray_new(void) {
@@ -117,30 +138,213 @@ static mrb_float sp_FloatArray_get(sp_FloatArray *array, mrb_int index) {
117
138
  return array->data[index];
118
139
  }
119
140
 
120
- static int sp_streq(const char *a, const char *b) {
121
- while (*a && *b && *a == *b) {
122
- a++;
123
- b++;
141
+ static volatile uint32_t rd_uno_timer0_overflows = 0;
142
+ static uint8_t rd_uno_timer0_ready = 0;
143
+
144
+ ISR(TIMER0_OVF_vect) {
145
+ rd_uno_timer0_overflows++;
146
+ }
147
+
148
+ static void rd_uno_timer0_init(void) {
149
+ if (rd_uno_timer0_ready) {
150
+ return;
124
151
  }
125
- return *a == *b;
152
+
153
+ TCCR0A |= (uint8_t)((1 << WGM00) | (1 << WGM01));
154
+ TCCR0B = (uint8_t)((TCCR0B & (uint8_t)~((1 << CS02) | (1 << CS01) | (1 << CS00))) | (1 << CS01) | (1 << CS00));
155
+ TIMSK0 |= (uint8_t)(1 << TOIE0);
156
+ rd_uno_timer0_ready = 1;
157
+ sei();
158
+ }
159
+
160
+ static int rd_uno_valid_pin(uint8_t pin) {
161
+ return pin <= 19;
126
162
  }
127
163
 
128
- static int sp_arduino_system(const char *cmd) {
129
- if (sp_streq(cmd, "pin13:output")) {
130
- DDRB |= _BV(DDB5);
164
+ static volatile uint8_t *rd_uno_ddr(uint8_t pin) {
165
+ if (pin <= 7) {
166
+ return &DDRD;
167
+ }
168
+ if (pin <= 13) {
169
+ return &DDRB;
170
+ }
171
+ if (pin <= 19) {
172
+ return &DDRC;
173
+ }
174
+ return NULL;
175
+ }
176
+
177
+ static volatile uint8_t *rd_uno_port(uint8_t pin) {
178
+ if (pin <= 7) {
179
+ return &PORTD;
180
+ }
181
+ if (pin <= 13) {
182
+ return &PORTB;
183
+ }
184
+ if (pin <= 19) {
185
+ return &PORTC;
186
+ }
187
+ return NULL;
188
+ }
189
+
190
+ static volatile uint8_t *rd_uno_pin_reg(uint8_t pin) {
191
+ if (pin <= 7) {
192
+ return &PIND;
193
+ }
194
+ if (pin <= 13) {
195
+ return &PINB;
196
+ }
197
+ if (pin <= 19) {
198
+ return &PINC;
199
+ }
200
+ return NULL;
201
+ }
202
+
203
+ static uint8_t rd_uno_bit(uint8_t pin) {
204
+ if (pin <= 7) {
205
+ return pin;
206
+ }
207
+ if (pin <= 13) {
208
+ return pin - 8;
209
+ }
210
+ return pin - 14;
211
+ }
212
+
213
+ int pin_mode(uint8_t pin, uint8_t mode) {
214
+ volatile uint8_t *ddr = rd_uno_ddr(pin);
215
+ volatile uint8_t *port = rd_uno_port(pin);
216
+ uint8_t mask;
217
+
218
+ if (!ddr || !port) {
219
+ return 1;
220
+ }
221
+
222
+ mask = (uint8_t)(1 << rd_uno_bit(pin));
223
+
224
+ if (mode == 1) {
225
+ *ddr |= mask;
131
226
  return 0;
132
227
  }
133
- if (sp_streq(cmd, "pin13:high")) {
134
- PORTB |= _BV(PORTB5);
228
+
229
+ if (mode == 0) {
230
+ *ddr &= (uint8_t)~mask;
231
+ *port &= (uint8_t)~mask;
135
232
  return 0;
136
233
  }
137
- if (sp_streq(cmd, "pin13:low")) {
138
- PORTB &= (uint8_t)~_BV(PORTB5);
234
+
235
+ if (mode == 2) {
236
+ *ddr &= (uint8_t)~mask;
237
+ *port |= mask;
139
238
  return 0;
140
239
  }
240
+
141
241
  return 1;
142
242
  }
143
243
 
244
+ int digital_write(uint8_t pin, uint8_t value) {
245
+ volatile uint8_t *port = rd_uno_port(pin);
246
+ uint8_t mask;
247
+
248
+ if (!port) {
249
+ return 1;
250
+ }
251
+
252
+ mask = (uint8_t)(1 << rd_uno_bit(pin));
253
+
254
+ if (value) {
255
+ *port |= mask;
256
+ } else {
257
+ *port &= (uint8_t)~mask;
258
+ }
259
+
260
+ return 0;
261
+ }
262
+
263
+ int digital_read(uint8_t pin) {
264
+ volatile uint8_t *reg = rd_uno_pin_reg(pin);
265
+
266
+ if (!reg) {
267
+ return -1;
268
+ }
269
+
270
+ return ((*reg & (uint8_t)(1 << rd_uno_bit(pin))) != 0) ? 1 : 0;
271
+ }
272
+
273
+ int analog_read(uint8_t pin) {
274
+ uint8_t channel = pin;
275
+
276
+ if (pin >= 14 && pin <= 19) {
277
+ channel = pin - 14;
278
+ }
279
+
280
+ if (channel > 5 || !rd_uno_valid_pin(pin)) {
281
+ return -1;
282
+ }
283
+
284
+ ADMUX = (uint8_t)((1 << REFS0) | channel);
285
+ ADCSRA = (uint8_t)((1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0));
286
+ ADCSRA |= (uint8_t)(1 << ADSC);
287
+
288
+ while (ADCSRA & (uint8_t)(1 << ADSC)) {
289
+ }
290
+
291
+ return ADC;
292
+ }
293
+
294
+ int analog_write(uint8_t pin, uint8_t value) {
295
+ if (!rd_uno_valid_pin(pin)) {
296
+ return 1;
297
+ }
298
+
299
+ pin_mode(pin, 1);
300
+
301
+ if (value == 0) {
302
+ return digital_write(pin, 0);
303
+ }
304
+ if (value == 255) {
305
+ return digital_write(pin, 1);
306
+ }
307
+
308
+ if (pin == 5) {
309
+ rd_uno_timer0_init();
310
+ TCCR0A |= (uint8_t)(1 << COM0B1);
311
+ OCR0B = value;
312
+ return 0;
313
+ }
314
+ if (pin == 6) {
315
+ rd_uno_timer0_init();
316
+ TCCR0A |= (uint8_t)(1 << COM0A1);
317
+ OCR0A = value;
318
+ return 0;
319
+ }
320
+ if (pin == 9) {
321
+ TCCR1A |= (uint8_t)((1 << WGM10) | (1 << COM1A1));
322
+ TCCR1B = (uint8_t)((TCCR1B & (uint8_t)~((1 << CS12) | (1 << CS11) | (1 << CS10) | (1 << WGM13))) | (1 << WGM12) | (1 << CS11) | (1 << CS10));
323
+ OCR1A = value;
324
+ return 0;
325
+ }
326
+ if (pin == 10) {
327
+ TCCR1A |= (uint8_t)((1 << WGM10) | (1 << COM1B1));
328
+ TCCR1B = (uint8_t)((TCCR1B & (uint8_t)~((1 << CS12) | (1 << CS11) | (1 << CS10) | (1 << WGM13))) | (1 << WGM12) | (1 << CS11) | (1 << CS10));
329
+ OCR1B = value;
330
+ return 0;
331
+ }
332
+ if (pin == 3) {
333
+ TCCR2A |= (uint8_t)((1 << WGM20) | (1 << WGM21) | (1 << COM2B1));
334
+ TCCR2B = (uint8_t)((TCCR2B & (uint8_t)~((1 << CS22) | (1 << CS21) | (1 << CS20))) | (1 << CS22));
335
+ OCR2B = value;
336
+ return 0;
337
+ }
338
+ if (pin == 11) {
339
+ TCCR2A |= (uint8_t)((1 << WGM20) | (1 << WGM21) | (1 << COM2A1));
340
+ TCCR2B = (uint8_t)((TCCR2B & (uint8_t)~((1 << CS22) | (1 << CS21) | (1 << CS20))) | (1 << CS22));
341
+ OCR2A = value;
342
+ return 0;
343
+ }
344
+
345
+ return digital_write(pin, value < 128 ? 0 : 1);
346
+ }
347
+
144
348
  static void sp_arduino_delay_ms(unsigned long ms) {
145
349
  while (ms > 0) {
146
350
  _delay_loop_2((uint16_t)(F_CPU / 4000UL));
@@ -148,12 +352,197 @@ static void sp_arduino_delay_ms(unsigned long ms) {
148
352
  }
149
353
  }
150
354
 
151
- static void sp_arduino_sleep_seconds(double seconds) {
152
- sp_arduino_delay_ms((unsigned long)(seconds * 1000.0 + 0.5));
355
+ void delay_ms(uint32_t ms) {
356
+ sp_arduino_delay_ms(ms);
357
+ }
358
+
359
+ void delay_us(uint32_t us) {
360
+ while (us > 0) {
361
+ _delay_us(1.0);
362
+ us--;
363
+ }
364
+ }
365
+
366
+ uint32_t micros(void) {
367
+ uint32_t overflows;
368
+ uint8_t counter;
369
+ uint8_t flags;
370
+ uint8_t sreg;
371
+
372
+ rd_uno_timer0_init();
373
+
374
+ sreg = SREG;
375
+ cli();
376
+ overflows = rd_uno_timer0_overflows;
377
+ counter = TCNT0;
378
+ flags = TIFR0;
379
+ if ((flags & (uint8_t)(1 << TOV0)) && counter < 255) {
380
+ overflows++;
381
+ }
382
+ SREG = sreg;
383
+
384
+ return ((overflows << 8) + counter) * (uint32_t)(64UL / (F_CPU / 1000000UL));
385
+ }
386
+
387
+ uint32_t millis(void) {
388
+ return micros() / 1000UL;
389
+ }
390
+
391
+ uint32_t pulse_in_timeout(uint8_t pin, uint8_t value, uint32_t timeout_us) {
392
+ uint32_t start;
393
+ uint32_t pulse_start;
394
+ uint32_t width;
395
+
396
+ if (!rd_uno_valid_pin(pin)) {
397
+ return 0;
398
+ }
399
+
400
+ value = value ? 1 : 0;
401
+ start = micros();
402
+
403
+ while (digital_read(pin) == value) {
404
+ if ((micros() - start) >= timeout_us) {
405
+ return 0;
406
+ }
407
+ }
408
+
409
+ while (digital_read(pin) != value) {
410
+ if ((micros() - start) >= timeout_us) {
411
+ return 0;
412
+ }
413
+ }
414
+
415
+ pulse_start = micros();
416
+
417
+ while (digital_read(pin) == value) {
418
+ width = micros() - pulse_start;
419
+ if ((micros() - start) >= timeout_us) {
420
+ return 0;
421
+ }
422
+ }
423
+
424
+ return micros() - pulse_start;
425
+ }
426
+
427
+ uint32_t pulse_in(uint8_t pin, uint8_t value) {
428
+ return pulse_in_timeout(pin, value, 1000000UL);
429
+ }
430
+
431
+ void serial_begin(uint32_t baud) {
432
+ uint16_t ubrr;
433
+
434
+ if (baud == 0) {
435
+ return;
436
+ }
437
+
438
+ ubrr = (uint16_t)((F_CPU / 16UL / baud) - 1UL);
439
+ UBRR0H = (uint8_t)(ubrr >> 8);
440
+ UBRR0L = (uint8_t)ubrr;
441
+ UCSR0A = 0;
442
+ UCSR0B = (uint8_t)((1 << RXEN0) | (1 << TXEN0));
443
+ UCSR0C = (uint8_t)((1 << UCSZ01) | (1 << UCSZ00));
444
+ }
445
+
446
+ int serial_available(void) {
447
+ return (UCSR0A & (uint8_t)(1 << RXC0)) ? 1 : 0;
448
+ }
449
+
450
+ int serial_read(void) {
451
+ if (!serial_available()) {
452
+ return -1;
453
+ }
454
+ return UDR0;
455
+ }
456
+
457
+ void serial_write(uint8_t value) {
458
+ while (!(UCSR0A & (uint8_t)(1 << UDRE0))) {
459
+ }
460
+ UDR0 = value;
461
+ }
462
+
463
+ void serial_print_str(const char *value) {
464
+ while (*value) {
465
+ serial_write((uint8_t)*value);
466
+ value++;
467
+ }
468
+ }
469
+
470
+ void serial_print_int(int value) {
471
+ char buf[12];
472
+ char *p = &buf[11];
473
+ unsigned int n;
474
+
475
+ *p = '\0';
476
+ if (value < 0) {
477
+ serial_write((uint8_t)'-');
478
+ n = (unsigned int)(-value);
479
+ } else {
480
+ n = (unsigned int)value;
481
+ }
482
+
483
+ do {
484
+ p--;
485
+ *p = (char)('0' + (n % 10));
486
+ n /= 10;
487
+ } while (n > 0);
488
+
489
+ serial_print_str(p);
490
+ }
491
+
492
+ void serial_println_str(const char *value) {
493
+ serial_print_str(value);
494
+ serial_write((uint8_t)'\r');
495
+ serial_write((uint8_t)'\n');
496
+ }
497
+
498
+ void serial_println_int(int value) {
499
+ serial_print_int(value);
500
+ serial_write((uint8_t)'\r');
501
+ serial_write((uint8_t)'\n');
502
+ }
503
+
504
+ uint8_t shift_in(uint8_t data_pin, uint8_t clock_pin, uint8_t bit_order) {
505
+ uint8_t value = 0;
506
+ uint8_t i;
507
+
508
+ for (i = 0; i < 8; i++) {
509
+ digital_write(clock_pin, 1);
510
+ if (bit_order == 0) {
511
+ value |= (uint8_t)(digital_read(data_pin) << i);
512
+ } else {
513
+ value |= (uint8_t)(digital_read(data_pin) << (7 - i));
514
+ }
515
+ digital_write(clock_pin, 0);
516
+ }
517
+
518
+ return value;
519
+ }
520
+
521
+ void shift_out(uint8_t data_pin, uint8_t clock_pin, uint8_t bit_order, uint8_t value) {
522
+ uint8_t i;
523
+ uint8_t bit;
524
+
525
+ for (i = 0; i < 8; i++) {
526
+ if (bit_order == 0) {
527
+ bit = (uint8_t)((value >> i) & 1);
528
+ } else {
529
+ bit = (uint8_t)((value >> (7 - i)) & 1);
530
+ }
531
+
532
+ digital_write(data_pin, bit);
533
+ digital_write(clock_pin, 1);
534
+ digital_write(clock_pin, 0);
535
+ }
536
+ }
537
+
538
+ void interrupts(void) {
539
+ sei();
540
+ }
541
+
542
+ void no_interrupts(void) {
543
+ cli();
153
544
  }
154
545
 
155
- #define system(cmd) sp_arduino_system(cmd)
156
- #define sleep(seconds) sp_arduino_delay_ms((unsigned long)((seconds) * 1000.0 + 0.5))
157
546
  #define fflush(stream) ((void)0)
158
547
 
159
548
  #endif
@@ -26,13 +26,20 @@ load_spinel_compiler
26
26
  module SpinelArduinoCodegen
27
27
  def compile_no_recv_call_expr(nid, mname)
28
28
  case mname
29
- when "sleep"
30
- compile_arduino_sleep(nid)
31
- "0"
32
29
  when "rand"
33
30
  arduino_rand = compile_arduino_rand(nid)
34
31
  return arduino_rand if arduino_rand
35
32
 
33
+ super
34
+ when "serial_print"
35
+ arduino_serial_print = compile_arduino_serial_print(nid, false)
36
+ return arduino_serial_print if arduino_serial_print
37
+
38
+ super
39
+ when "serial_println"
40
+ arduino_serial_print = compile_arduino_serial_print(nid, true)
41
+ return arduino_serial_print if arduino_serial_print
42
+
36
43
  super
37
44
  else
38
45
  super
@@ -41,19 +48,24 @@ module SpinelArduinoCodegen
41
48
 
42
49
  private
43
50
 
44
- def compile_arduino_sleep(nid)
51
+ def compile_arduino_serial_print(nid, newline)
45
52
  args_id = @nd_arguments[nid]
46
- return if args_id < 0
53
+ return nil if args_id < 0
47
54
 
48
55
  arg_ids = get_args(args_id)
49
- return if arg_ids.empty?
56
+ return nil unless arg_ids.length == 1
50
57
 
51
58
  arg = arg_ids.first
52
- if numeric_literal_node?(arg)
53
- emit_arduino_delay_literal(numeric_literal_value(arg))
54
- else
55
- emit(" sp_arduino_sleep_seconds(" + compile_expr(arg) + ");")
59
+ fn = arduino_serial_print_func(arg, newline)
60
+ "(" + fn + "(" + compile_expr(arg) + "), (mrb_int)0)"
61
+ end
62
+
63
+ def arduino_serial_print_func(arg, newline)
64
+ if infer_type(arg) == "string"
65
+ return newline ? "serial_println_str" : "serial_print_str"
56
66
  end
67
+
68
+ newline ? "serial_println_int" : "serial_print_int"
57
69
  end
58
70
 
59
71
  def compile_arduino_rand(nid)
@@ -79,32 +91,9 @@ module SpinelArduinoCodegen
79
91
  "((mrb_int)(#{first} + (rand() % #{span})))"
80
92
  end
81
93
 
82
- def emit_arduino_delay_literal(seconds)
83
- ms = (seconds * 1000.0).round
84
- parts = []
85
- while ms >= 250
86
- parts << "_delay_ms(250.0)"
87
- ms -= 250
88
- end
89
- parts << "_delay_ms(#{ms}.0)" if ms > 0
90
- emit(" " + parts.join("; ") + ";") unless parts.empty?
91
- end
92
-
93
94
  def integer_literal_node?(nid)
94
95
  nid && nid >= 0 && @nd_type[nid] == "IntegerNode"
95
96
  end
96
-
97
- def numeric_literal_node?(nid)
98
- nid && nid >= 0 && %w[IntegerNode FloatNode].include?(@nd_type[nid])
99
- end
100
-
101
- def numeric_literal_value(nid)
102
- if @nd_type[nid] == "IntegerNode"
103
- @nd_value[nid].to_f
104
- else
105
- @nd_content[nid].to_f
106
- end
107
- end
108
97
  end
109
98
 
110
99
  Compiler.prepend(SpinelArduinoCodegen)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rubyduino
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubyduino
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Schito
@@ -24,9 +24,11 @@ files:
24
24
  - README.md
25
25
  - Rakefile
26
26
  - bin/rubyduino
27
+ - examples/hc_sr04.rb
27
28
  - examples/hello.rb
28
29
  - lib/rubyduino.rb
29
30
  - lib/rubyduino/arduino_entry.c
31
+ - lib/rubyduino/arduino_uno.rb
30
32
  - lib/rubyduino/sp_runtime.h
31
33
  - lib/rubyduino/spinel.rb
32
34
  - lib/rubyduino/spinel_arduino_codegen.rb