1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Services to control the bcm2835 chipset as used in the Raspberry Pi
18 # model B revision 1 Uses the C library by Mike McCauley from
19 # http://www.airspayce.com/mikem/bcm2835/
29 protected fun bcm2835_init
: Bool `{ return bcm2835_init(); `}
30 protected fun bcm2835_close `{ bcm2835_close(); `}
31 protected fun bcm2835_debug
=(v
: Bool) `{ bcm2835_set_debug(v); `}
34 extern class RPiPin `{ RPiGPIOPin `}
37 new p1_03
`{ return RPI_GPIO_P1_03; `}
39 new p1_05 `{ return RPI_GPIO_P1_05; `}
40 new p1_07
`{ return RPI_GPIO_P1_07; `}
42 new p1_11 `{ return RPI_GPIO_P1_11; `}
43 new p1_12
`{ return RPI_GPIO_P1_12; `}
44 new p1_13 `{ return RPI_GPIO_P1_13; `}
46 new p1_15
`{ return RPI_GPIO_P1_15; `}
47 new p1_16 `{ return RPI_GPIO_P1_16; `}
49 new p1_18
`{ return RPI_GPIO_P1_18; `}
50 new p1_19 `{ return RPI_GPIO_P1_19; `}
52 new p1_21
`{ return RPI_GPIO_P1_21; `}
53 new p1_22 `{ return RPI_GPIO_P1_22; `}
54 new p1_23
`{ return RPI_GPIO_P1_23; `}
55 new p1_24 `{ return RPI_GPIO_P1_24; `}
57 new p1_26
`{ return RPI_GPIO_P1_26; `}
59 # Select mode: input, output or alts
60 fun fsel=(mode: FunctionSelect) `{ bcm2835_gpio_fsel(recv, mode); `}
63 redef fun write
(high
) `{ bcm2835_gpio_write(recv, high? HIGH: LOW); `}
66 fun pud=(pud: PUDControl) `{ bcm2835_gpio_set_pud(recv, pud); `}
69 # Do not use on raspbian, it is bugged!
70 fun fen
`{ bcm2835_gpio_fen(recv); `}
71 fun clr_fen `{ bcm2835_gpio_clr_fen(recv); `}
74 # Do not use on raspbian, it is bugged!
75 fun ren
`{ bcm2835_gpio_ren(recv); `}
76 fun clr_ren `{ bcm2835_gpio_clr_ren(recv); `}
79 # Do not use on raspbian, it is bugged!
80 fun hen
`{ bcm2835_gpio_hen(recv); `}
81 fun clr_hen `{ bcm2835_gpio_clr_hen(recv); `}
84 # Do not use on raspbian, it is bugged!
85 fun len
`{ bcm2835_gpio_len(recv); `}
86 fun clr_len `{ bcm2835_gpio_clr_len(recv); `}
88 fun set_eds
`{ bcm2835_gpio_set_eds(recv); `}
89 fun eds: Bool `{ return bcm2835_gpio_eds(recv); `}
91 # Return input on pin, true for high and false for low
92 fun lev
: Bool `{ return bcm2835_gpio_lev(recv); `}
95 extern class FunctionSelect `{ bcm2835FunctionSelect `}
97 new inpt
`{ return BCM2835_GPIO_FSEL_INPT; `}
100 new outp `{ return BCM2835_GPIO_FSEL_OUTP; `}
102 new alt0
`{ return BCM2835_GPIO_FSEL_ALT0; `}
103 new alt1 `{ return BCM2835_GPIO_FSEL_ALT1; `}
104 new alt2
`{ return BCM2835_GPIO_FSEL_ALT2; `}
105 new alt3 `{ return BCM2835_GPIO_FSEL_ALT3; `}
106 new alt4
`{ return BCM2835_GPIO_FSEL_ALT4; `}
107 new alt5 `{ return BCM2835_GPIO_FSEL_ALT5; `}
108 new mask
`{ return BCM2835_GPIO_FSEL_MASK; `}
111 extern class PUDControl `{ bcm2835PUDControl `}
112 new off
`{ return BCM2835_GPIO_PUD_OFF; `}
113 new down `{ return BCM2835_GPIO_PUD_DOWN; `}
114 new up
`{ return BCM2835_GPIO_PUD_UP; `}
118 fun bcm2835_delay `{ bcm2835_delay(recv); `}
119 fun bcm2835_delay_micros
`{ bcm2835_delayMicroseconds(recv); `}
128 # returns '<', '>' or null accoring to rotation or lack thereof
129 fun update: nullable Char
131 var new_a = pin_a.lev
132 var new_b = pin_b.lev
135 if new_a != old_a or new_b != old_b then
136 if not old_a and not old_b then
138 if not new_a and new_b then
140 else if new_a and not new_b then
143 else if old_a and old_b then
145 if not new_a and new_b then
147 else if new_a and not new_b then
160 # Hitachi HD44780 or similar 2-4 lines LCD displays
169 var ds = new Array[RPiPin]
172 fun flag_clear_display: Int do return 1
173 fun flag_return_home: Int do return 2
174 fun flag_entry_mode_set: Int do return 4
175 fun flag_display_control: Int do return 8
176 fun flag_cursor_shift: Int do return 16
177 fun flag_function_set: Int do return 32
178 fun flag_set_cgram_addr: Int do return 64
179 fun flag_set_ggram_addr: Int do return 128
182 fun flag_entry_right: Int do return 0
183 fun flag_entry_left: Int do return 2
184 fun flag_entry_shift_increment: Int do return 1
185 fun flag_entry_shift_decrement: Int do return 0
188 fun flag_display_on: Int do return 4
189 fun flag_display_off: Int do return 0
190 fun flag_cursor_on: Int do return 2
191 fun flag_cursor_off: Int do return 0
192 fun flag_blink_on: Int do return 1
193 fun flag_blink_off: Int do return 0
195 # display/cursor shift
196 fun flag_display_move: Int do return 8
197 fun flag_cursor_move: Int do return 0
198 fun flag_move_right: Int do return 4
199 fun flag_move_left: Int do return 0
202 fun flag_8bit_mode: Int do return 16
203 fun flag_4bit_mode: Int do return 0
204 fun flag_2_lines: Int do return 8
205 fun flag_1_line: Int do return 0
206 fun flag_5x10_dots: Int do return 4
207 fun flag_5x8_dots: Int do return 0
209 # last text displayed
210 private var last_text: nullable String = null
212 fun function_set(bits, lines, dots_wide: Int)
214 var fs = flag_function_set
217 else if bits != 4 then abort
221 else if lines != 1 then abort
223 if dots_wide == 10 then
225 else if dots_wide != 8 then abort
230 fun display_control(on, cursor, blink: Bool)
232 var fs = flag_display_control
235 fs = fs.bin_or(flag_display_on)
236 else fs = fs.bin_or(flag_display_off)
239 fs = fs.bin_or(flag_cursor_on)
240 else fs = fs.bin_or(flag_cursor_off)
243 fs = fs.bin_or(flag_blink_on)
244 else fs = fs.bin_or(flag_blink_off)
249 fun entry_mode(left, incr: Bool)
251 var fs = flag_entry_mode_set
254 fs = fs.bin_or(flag_entry_left)
255 else fs = fs.bin_or(flag_entry_right)
258 fs = fs.bin_or(flag_entry_shift_increment)
259 else fs = fs.bin_or(flag_entry_shift_decrement)
268 rs.fsel = new FunctionSelect.outp
269 en.fsel = new FunctionSelect.outp
270 d4.fsel = new FunctionSelect.outp
271 d5.fsel = new FunctionSelect.outp
272 d6.fsel = new FunctionSelect.outp
273 d7.fsel = new FunctionSelect.outp
278 # wait 20ms for power up
281 write_4bits(true,true,false,false)
286 write_4bits(true,true,false,false)
291 write_4bits(true,true,false,false)
294 200.bcm2835_delay_micros
296 write_4bits(false,true,false,false)
304 function_set(4, 2, 8)
308 display_control(true, true, true)
313 # set cursor move direction
321 entry_mode(true, true)
328 rs.fsel = new FunctionSelect.outp
329 en.fsel = new FunctionSelect.outp
330 d4.fsel = new FunctionSelect.outp
331 d5.fsel = new FunctionSelect.outp
332 d6.fsel = new FunctionSelect.outp
333 d7.fsel = new FunctionSelect.outp
338 write(true, "33".to_hex) # init
339 write(true, "32".to_hex) # init
340 write(true, "28".to_hex) # 2 lines, 5x7
341 write(true, "0C".to_hex) # hide cursor
342 write(true, "06".to_hex) # cursor move right
343 write(true, "04".to_hex) # turn on display
344 write(true, "01".to_hex) # clear display
347 fun write_4_bits(v: Int)
349 var lb = once [1,2,4,8]
352 var r = b.bin_and(v) != 0
359 fun write_4bits(a,b,c,d:Bool)
371 1.bcm2835_delay_micros
373 100.bcm2835_delay_micros
375 1.bcm2835_delay_micros
378 fun write(is_cmd: Bool, cmd: Int)
384 var hb = once [16,32,64,128]
387 var r = b.bin_and(cmd) != 0
399 200.bcm2835_delay_micros
403 var lb = once [1,2,4,8]
406 var r = b.bin_and(cmd) != 0
418 200.bcm2835_delay_micros
436 # do not redraw the samething
437 var last_text = last_text
438 if last_text != null and last_text == v then return
445 # FIXME, this should work
446 #write(true, "C0".to_hex)
447 # instead we use the following which may not be portable
449 for s in [count..40[ do write(false, ' '.ascii)
452 write(false, c.ascii)
461 # Component for any kind of buttons or switches
465 init (pin: RPiPin, pud: PUDControl)
468 pin.fsel = new FunctionSelect.inpt
472 fun is_down: Bool do return pin.lev
474 var last_down: nullable Bool = null
476 # Returns true is state (is_down) changed since last call to `changed
`
480 var last_down = last_down
481 if last_down == null then
484 else if last_down != now then
492 var pins: Sequence[RPiPin]
495 init (delay: Int, a, b, c, d: RPiPin)
500 for p in pins do p.fsel = new FunctionSelect.outp
503 fun forward(steps: Int)
505 for s in [0..steps[ do
506 set(true, false, false, false)
508 set(true, true, false, false)
510 set(false, true, false, false)
512 set(false, true, true, false)
514 set(false, false, true, false)
516 set(false, false, true, true)
518 set(false, false, false, true)
520 set(true, false, false, true)
525 fun backwards(steps: Int)
527 for s in [0..steps[ do
528 set(true, false, false, true)
530 set(false, false, false, true)
532 set(false, false, true, true)
534 set(false, false, true, false)
536 set(false, true, true, false)
538 set(false, true, false, false)
540 set(true, true, false, false)
542 set(true, false, false, false)
547 fun release do set(false, false, false, false)
549 protected fun set(a, b, c, d: Bool)
551 var bits = new Array[Bool].with_items(a, b, c, d)
553 for i in [0..4[ do pins[i].write(bits[i])
560 fun buzz(delay: Float, times: Int)
564 var delay_i = (delay*1000.0).to_i
565 for i in [0..times[ do
567 delay_i.bcm2835_delay_micros
569 delay_i.bcm2835_delay_micros