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 +4 -4
- data/CHANGELOG.md +16 -4
- data/README.md +7 -7
- data/bin/rubyduino +6 -1
- data/examples/hc_sr04.rb +39 -0
- data/examples/hello.rb +5 -6
- data/lib/rubyduino/arduino_uno.rb +119 -0
- data/lib/rubyduino/sp_runtime.h +407 -18
- data/lib/rubyduino/spinel_arduino_codegen.rb +22 -33
- data/lib/rubyduino/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bac10de4fac724a35791684086ec7ac0ab440f2e3272e75d665f58a1b0d94f8d
|
|
4
|
+
data.tar.gz: f0c542257835047dda8edcfdd6d1c1480c27b1f2dd596f3e9e0f32303df06c81
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c544a3120274e0a8dc7cd53d24438c17fe4a72e6abab2c35d6130b0d1568e4f0d95d40490415fbd0a60303a89a25d9334b4f3e5f8e510b07f1046cce0193a3ac
|
|
7
|
+
data.tar.gz: 5ffcf8876947fa43e4d7cc9a15b6329df635230b9f397ed807cf58466e0d142e5c2ab2aa1fa1490914e848f5fc5db2e0f9d1cec54f72bd3b2468cf3b6bd636f6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
-
## [0.
|
|
3
|
+
## [0.2.0] - 2026-05-08
|
|
4
4
|
|
|
5
|
-
-
|
|
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.
|
|
9
|
+
## [0.1.3] - 2026-05-08
|
|
8
10
|
|
|
9
|
-
-
|
|
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
|
-
|
|
19
|
+
pin_mode(ArduinoUNO::LED_BUILTIN, ArduinoUNO::OUTPUT)
|
|
19
20
|
|
|
20
21
|
loop do
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
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
|
data/examples/hc_sr04.rb
ADDED
|
@@ -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
|
-
|
|
1
|
+
pin_mode(ArduinoUNO::LED_BUILTIN, ArduinoUNO::OUTPUT)
|
|
2
2
|
|
|
3
3
|
loop do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
data/lib/rubyduino/sp_runtime.h
CHANGED
|
@@ -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
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
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
|
|
129
|
-
if (
|
|
130
|
-
|
|
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
|
-
|
|
134
|
-
|
|
228
|
+
|
|
229
|
+
if (mode == 0) {
|
|
230
|
+
*ddr &= (uint8_t)~mask;
|
|
231
|
+
*port &= (uint8_t)~mask;
|
|
135
232
|
return 0;
|
|
136
233
|
}
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
152
|
-
sp_arduino_delay_ms(
|
|
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
|
|
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
|
|
56
|
+
return nil unless arg_ids.length == 1
|
|
50
57
|
|
|
51
58
|
arg = arg_ids.first
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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)
|
data/lib/rubyduino/version.rb
CHANGED
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.
|
|
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
|