-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArdCom.dyalog
167 lines (136 loc) · 4.64 KB
/
ArdCom.dyalog
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
:Class ArdCom
⍝ Object-oriented wrapper for an Arduino running "ArdCom version 0.2 or later"
⍝∇:require =/I2C
⎕IO←⎕ML←1 ⍝ Condition the environment
_version←0.2
:Field Public Version←¯1 ⍝ Version not checked yet
:Field Public Trace←0 ⍝ Set to 1 to see all Sends
:Field Public Testing←0 ⍝ Set to 1 to not actually issue I2C commands
_pins←0 3⍴0 ⍝ Internal state
⍝ Pins: [;1] Pin # (nb A0..A5 = 14-19)
⍝ [;2] Type: A,D,S = OUTPUT: Analog, Diginal, Sonar (PWM)
⍝ a,d,p = INPUT: Analog, Digital, Pulse-driven Analog
⍝ [;3] "Info", only used for 'p': Pin used to send pulse
:Property Pins
:Access Public
∇ r←Get args
r←_pins
∇
∇ Set args;pins;shape;p;n;z
:If 2≠⍴shape←⍴pins←args.NewValue
:OrIf ~(2⊃shape)∊2 3
'Pins: [;1] Pin #, [;2] Type, [;3] Optional Extra Info'⎕SIGNAL 701
:EndIf
:If 2=⊃shape ⋄ pins←pins,0 ⋄ :EndIf ⍝ Add optional info if missing
p←pins
z←Reset
:While 0≠1↑⍴p
Send'S',,(n←4⌊1↑⍴p)↑p
p←n↓p
:EndWhile
_pins←pins
{}Identify ⍝ Forces verification of pins
∇
:EndProperty
getnum←{2⊃⎕VFI ⍵}
∇ {r}←Send bytes;i
:Access Public
⍝ I2C.WriteBytes, auto-coverting chars to ints and adding command length
bytes←,bytes
:Select ⎕DR bytes
:Case 80 ⋄ bytes←⎕UCS bytes
:Case 326 ⋄ bytes[i]←⎕UCS bytes[i←{⍵/⍳⍴⍵}80=⎕DR¨bytes]
:CaseList 83 11 ⍝ OK
:Else
⎕SIGNAL 11
:EndSelect
bytes←(⍴bytes),bytes
:If Trace∨Testing
⎕←'ArdCom.Send: ',⍕bytes
:EndIf
:If 0≠1⊃r←#.I2C.WriteBytes I2C_ADDRESS bytes 255
:AndIf 0≠1⊃r←#.I2C.WriteBytes I2C_ADDRESS bytes 255 ⍝ Retry once
('I2C.WriteBytes failed: ',⍕r)⎕SIGNAL 701
:EndIf
⎕DL 0.03
∇
∇ r←ReadBytes;z;log;l
:Access Public
log←''
:Repeat
:If 0≠1⊃z←#.I2C.ReadBytes I2C_ADDRESS(32⍴255)255
('I2C.ReadBytes failed: ',⍕z)⎕SIGNAL 701
:EndIf
:If l←254=1↑r←2⊃z ⋄ log,←⎕UCS 1↓r ⋄ :EndIf ⍝ Diagnostic output
:Until ~l
:If 0≠⍴log ⋄ ⎕←log ⋄ :EndIf
∇
∇ r←ReadChar;z
:Access Public
r←⎕UCS ReadBytes
∇
∇ r←ReadData;z
:Access Public
:If 0≠2|⍴r←¯1↓ReadBytes ⋄ ∘ ⋄ :EndIf ⍝ Not returning pairs of bytes!
r←256⊥⍉((0.5×⍴r),2)⍴r
∇
∇ Make args;z;data;ver;r
:Access Public
:Implements Constructor
⍝ ResetSignals
(I2C_ADDRESS I2C_BUS)←2↑args,(⍴,args)↓4 1
:If 0=⎕NC'#.I2C.Close'
:If 0≠z←#.I2C.Init ⍬
('I2C.Init failed: ',⍕z)⎕SIGNAL 701
:EndIf
:EndIf
:If 0≠1⊃z←#.I2C.Open I2C_BUS 0 0
('I2C.Open failed: ',⍕z)⎕SIGNAL 701
:EndIf
{}⎕DL 0.1 ⍝ Stabilize
r←Reset
∇
∇ {r}←Reset
:Access Public
_pins←0 3⍴0
r←Send'R'
ReadChar
r←Identify
∇
∇ r←Identify;ver;pins;reported;data;expected
:Access Public
Send'I'
data←ReadChar
:If ~∧/(ver←2↑data)∊⎕D
('I did not return version#: ',data)⎕SIGNAL 701
:EndIf
Version←0.1×10⊥¯1+⎕D⍳ver
:If Version≠_version
('Arduino is running v',(⍕Version),', v',(⍕_version),' is required')⎕SIGNAL 701
:EndIf
:If 2<⍴data ⍝ Some pins are set up
pins←({((⌈0.5×⍴⍵),2)⍴⍵}2↓data),0
pins[;1]←⎕UCS pins[;1]
:Else
pins←0 3⍴0
:EndIf
reported←↓pins[;1 2] ⋄ expected←↓_pins[;1 2]
:If ~∧/(reported∊expected),expected∊reported
⎕←2 2⍴'reported' 'expected'reported expected
∘ ⍝ Internal error: Mismatch between reported and expected pins
:EndIf
r←Version _pins
∇
∇ UnMake;z
:Implements Destructor
⍝:If ~Testing
⍝ z←#.I2C.Close 0
⍝:EndIf
∇
∇ ResetSignals
⍝ Reset signal handling: Workaround for issue with libi2c
:Trap 11
{⎕SIGNAL ⍵}11
:EndTrap
∇
:EndClass