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 used in the Raspberry Pi
19 # Uses the C library by Mike McCauley available at http://www.airspayce.com/mikem/bcm2835/
21 # This module targets the model B revision 1, it could be tweaked for other versions.
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 # A physical binary pin
36 # Set the output of this pin
37 fun write(high: Bool) is abstract
40 extern class RPiPin `{ RPiGPIOPin `}
43 new p1_03
`{ return RPI_GPIO_P1_03; `}
45 new p1_05 `{ return RPI_GPIO_P1_05; `}
46 new p1_07
`{ return RPI_GPIO_P1_07; `}
48 new p1_11 `{ return RPI_GPIO_P1_11; `}
49 new p1_12
`{ return RPI_GPIO_P1_12; `}
50 new p1_13 `{ return RPI_GPIO_P1_13; `}
52 new p1_15
`{ return RPI_GPIO_P1_15; `}
53 new p1_16 `{ return RPI_GPIO_P1_16; `}
55 new p1_18
`{ return RPI_GPIO_P1_18; `}
56 new p1_19 `{ return RPI_GPIO_P1_19; `}
58 new p1_21
`{ return RPI_GPIO_P1_21; `}
59 new p1_22 `{ return RPI_GPIO_P1_22; `}
60 new p1_23
`{ return RPI_GPIO_P1_23; `}
61 new p1_24 `{ return RPI_GPIO_P1_24; `}
63 new p1_26
`{ return RPI_GPIO_P1_26; `}
65 # Select mode: input, output or alts
66 fun fsel=(mode: FunctionSelect) `{ bcm2835_gpio_fsel(self, mode); `}
69 redef fun write
(high
) `{ bcm2835_gpio_write(self, high? HIGH: LOW); `}
72 fun pud=(pud: PUDControl) `{ bcm2835_gpio_set_pud(self, pud); `}
75 # Do not use on raspbian, it is bugged!
76 fun fen
`{ bcm2835_gpio_fen(self); `}
77 fun clr_fen `{ bcm2835_gpio_clr_fen(self); `}
80 # Do not use on raspbian, it is bugged!
81 fun ren
`{ bcm2835_gpio_ren(self); `}
82 fun clr_ren `{ bcm2835_gpio_clr_ren(self); `}
85 # Do not use on raspbian, it is bugged!
86 fun hen
`{ bcm2835_gpio_hen(self); `}
87 fun clr_hen `{ bcm2835_gpio_clr_hen(self); `}
90 # Do not use on raspbian, it is bugged!
91 fun len
`{ bcm2835_gpio_len(self); `}
92 fun clr_len `{ bcm2835_gpio_clr_len(self); `}
94 fun set_eds
`{ bcm2835_gpio_set_eds(self); `}
95 fun eds: Bool `{ return bcm2835_gpio_eds(self); `}
97 # Return input on pin, true for high and false for low
98 fun lev
: Bool `{ return bcm2835_gpio_lev(self); `}
101 extern class FunctionSelect `{ bcm2835FunctionSelect `}
103 new inpt
`{ return BCM2835_GPIO_FSEL_INPT; `}
106 new outp `{ return BCM2835_GPIO_FSEL_OUTP; `}
108 new alt0
`{ return BCM2835_GPIO_FSEL_ALT0; `}
109 new alt1 `{ return BCM2835_GPIO_FSEL_ALT1; `}
110 new alt2
`{ return BCM2835_GPIO_FSEL_ALT2; `}
111 new alt3 `{ return BCM2835_GPIO_FSEL_ALT3; `}
112 new alt4
`{ return BCM2835_GPIO_FSEL_ALT4; `}
113 new alt5 `{ return BCM2835_GPIO_FSEL_ALT5; `}
114 new mask
`{ return BCM2835_GPIO_FSEL_MASK; `}
117 extern class PUDControl `{ bcm2835PUDControl `}
118 new off
`{ return BCM2835_GPIO_PUD_OFF; `}
119 new down `{ return BCM2835_GPIO_PUD_DOWN; `}
120 new up
`{ return BCM2835_GPIO_PUD_UP; `}
124 fun bcm2835_delay `{ bcm2835_delay(self); `}
125 fun bcm2835_delay_micros
`{ bcm2835_delayMicroseconds(self); `}
134 # returns '<', '>' or null accoring to rotation or lack thereof
135 fun update: nullable Char
137 var new_a = pin_a.lev
138 var new_b = pin_b.lev
141 if new_a != old_a or new_b != old_b then
142 if not old_a and not old_b then
144 if not new_a and new_b then
146 else if new_a and not new_b then
149 else if old_a and old_b then
151 if not new_a and new_b then
153 else if new_a and not new_b then
166 # Hitachi HD44780 or similar 2-4 lines LCD displays
175 var ds = new Array[RPiPin]
178 fun flag_clear_display: Int do return 1
179 fun flag_return_home: Int do return 2
180 fun flag_entry_mode_set: Int do return 4
181 fun flag_display_control: Int do return 8
182 fun flag_cursor_shift: Int do return 16
183 fun flag_function_set: Int do return 32
184 fun flag_set_cgram_addr: Int do return 64
185 fun flag_set_ggram_addr: Int do return 128
188 fun flag_entry_right: Int do return 0
189 fun flag_entry_left: Int do return 2
190 fun flag_entry_shift_increment: Int do return 1
191 fun flag_entry_shift_decrement: Int do return 0
194 fun flag_display_on: Int do return 4
195 fun flag_display_off: Int do return 0
196 fun flag_cursor_on: Int do return 2
197 fun flag_cursor_off: Int do return 0
198 fun flag_blink_on: Int do return 1
199 fun flag_blink_off: Int do return 0
201 # display/cursor shift
202 fun flag_display_move: Int do return 8
203 fun flag_cursor_move: Int do return 0
204 fun flag_move_right: Int do return 4
205 fun flag_move_left: Int do return 0
208 fun flag_8bit_mode: Int do return 16
209 fun flag_4bit_mode: Int do return 0
210 fun flag_2_lines: Int do return 8
211 fun flag_1_line: Int do return 0
212 fun flag_5x10_dots: Int do return 4
213 fun flag_5x8_dots: Int do return 0
215 # last text displayed
216 private var last_text: nullable String = null
218 fun function_set(bits, lines, dots_wide: Int)
220 var fs = flag_function_set
223 else if bits != 4 then abort
227 else if lines != 1 then abort
229 if dots_wide == 10 then
231 else if dots_wide != 8 then abort
236 fun display_control(on, cursor, blink: Bool)
238 var fs = flag_display_control
240 fs |= if on then flag_display_on else flag_display_off
242 fs |= if cursor then flag_cursor_on else flag_cursor_off
244 fs |= if blink then flag_blink_on else flag_blink_off
249 fun entry_mode(left, incr: Bool)
251 var fs = flag_entry_mode_set
253 fs |= if left then flag_entry_left else flag_entry_right
255 fs |= if incr then flag_entry_shift_increment else flag_entry_shift_decrement
264 rs.fsel = new FunctionSelect.outp
265 en.fsel = new FunctionSelect.outp
266 d4.fsel = new FunctionSelect.outp
267 d5.fsel = new FunctionSelect.outp
268 d6.fsel = new FunctionSelect.outp
269 d7.fsel = new FunctionSelect.outp
274 # wait 20ms for power up
277 write_4bits(true,true,false,false)
282 write_4bits(true,true,false,false)
287 write_4bits(true,true,false,false)
290 200.bcm2835_delay_micros
292 write_4bits(false,true,false,false)
300 function_set(4, 2, 8)
304 display_control(true, true, true)
309 # set cursor move direction
317 entry_mode(true, true)
324 rs.fsel = new FunctionSelect.outp
325 en.fsel = new FunctionSelect.outp
326 d4.fsel = new FunctionSelect.outp
327 d5.fsel = new FunctionSelect.outp
328 d6.fsel = new FunctionSelect.outp
329 d7.fsel = new FunctionSelect.outp
334 write(true, "33".to_hex) # init
335 write(true, "32".to_hex) # init
336 write(true, "28".to_hex) # 2 lines, 5x7
337 write(true, "0C".to_hex) # hide cursor
338 write(true, "06".to_hex) # cursor move right
339 write(true, "04".to_hex) # turn on display
340 write(true, "01".to_hex) # clear display
343 fun write_4_bits(v: Int)
345 var lb = once [1,2,4,8]
355 fun write_4bits(a,b,c,d:Bool)
367 1.bcm2835_delay_micros
369 100.bcm2835_delay_micros
371 1.bcm2835_delay_micros
374 fun write(is_cmd: Bool, cmd: Int)
380 var hb = once [16,32,64,128]
395 200.bcm2835_delay_micros
399 var lb = once [1,2,4,8]
414 200.bcm2835_delay_micros
432 # do not redraw the samething
433 var last_text = last_text
434 if last_text != null and last_text == v then return
441 # FIXME, this should work
442 #write(true, "C0".to_hex)
443 # instead we use the following which may not be portable
445 for s in [count..40[ do write(false, ' '.ascii)
448 write(false, c.ascii)
457 # Component for any kind of buttons or switches
461 init (pin: RPiPin, pud: PUDControl)
464 pin.fsel = new FunctionSelect.inpt
468 fun is_down: Bool do return pin.lev
470 var last_down: nullable Bool = null
472 # Returns true is state (is_down) changed since last call to `changed
`
476 var last_down = last_down
477 if last_down == null then
480 else if last_down != now then
488 var pins: Sequence[RPiPin]
491 init (delay: Int, a, b, c, d: RPiPin)
496 for p in pins do p.fsel = new FunctionSelect.outp
499 fun forward(steps: Int)
501 for s in [0..steps[ do
502 set(true, false, false, false)
504 set(true, true, false, false)
506 set(false, true, false, false)
508 set(false, true, true, false)
510 set(false, false, true, false)
512 set(false, false, true, true)
514 set(false, false, false, true)
516 set(true, false, false, true)
521 fun backwards(steps: Int)
523 for s in [0..steps[ do
524 set(true, false, false, true)
526 set(false, false, false, true)
528 set(false, false, true, true)
530 set(false, false, true, false)
532 set(false, true, true, false)
534 set(false, true, false, false)
536 set(true, true, false, false)
538 set(true, false, false, false)
543 fun release do set(false, false, false, false)
545 protected fun set(a, b, c, d: Bool)
547 var bits = new Array[Bool].with_items(a, b, c, d)
549 for i in [0..4[ do pins[i].write(bits[i])
556 fun buzz(delay: Float, times: Int)
560 var delay_i = (delay*1000.0).to_i
561 for i in [0..times[ do
563 delay_i.bcm2835_delay_micros
565 delay_i.bcm2835_delay_micros