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.
28 fun bcm2835_init
: Bool `{ return bcm2835_init(); `}
29 fun bcm2835_close `{ bcm2835_close(); `}
30 fun bcm2835_debug
=(v
: Bool) `{ bcm2835_set_debug(v); `}
32 # A physical binary pin
34 # Set the output of this pin
35 fun write(high: Bool) is abstract
38 extern class RPiPin `{ RPiGPIOPin `}
41 new p1_03
`{ return RPI_GPIO_P1_03; `}
43 new p1_05 `{ return RPI_GPIO_P1_05; `}
44 new p1_07
`{ return RPI_GPIO_P1_07; `}
46 new p1_11 `{ return RPI_GPIO_P1_11; `}
47 new p1_12
`{ return RPI_GPIO_P1_12; `}
48 new p1_13 `{ return RPI_GPIO_P1_13; `}
50 new p1_15
`{ return RPI_GPIO_P1_15; `}
51 new p1_16 `{ return RPI_GPIO_P1_16; `}
53 new p1_18
`{ return RPI_GPIO_P1_18; `}
54 new p1_19 `{ return RPI_GPIO_P1_19; `}
56 new p1_21
`{ return RPI_GPIO_P1_21; `}
57 new p1_22 `{ return RPI_GPIO_P1_22; `}
58 new p1_23
`{ return RPI_GPIO_P1_23; `}
59 new p1_24 `{ return RPI_GPIO_P1_24; `}
61 new p1_26
`{ return RPI_GPIO_P1_26; `}
63 # Select mode: input, output or alts
64 fun fsel=(mode: FunctionSelect) `{ bcm2835_gpio_fsel(self, mode); `}
67 redef fun write
(high
) `{ bcm2835_gpio_write(self, high? HIGH: LOW); `}
70 fun pud=(pud: PUDControl) `{ bcm2835_gpio_set_pud(self, pud); `}
73 # Do not use on raspbian, it is bugged!
74 fun fen
`{ bcm2835_gpio_fen(self); `}
75 fun clr_fen `{ bcm2835_gpio_clr_fen(self); `}
78 # Do not use on raspbian, it is bugged!
79 fun ren
`{ bcm2835_gpio_ren(self); `}
80 fun clr_ren `{ bcm2835_gpio_clr_ren(self); `}
83 # Do not use on raspbian, it is bugged!
84 fun hen
`{ bcm2835_gpio_hen(self); `}
85 fun clr_hen `{ bcm2835_gpio_clr_hen(self); `}
88 # Do not use on raspbian, it is bugged!
89 fun len
`{ bcm2835_gpio_len(self); `}
90 fun clr_len `{ bcm2835_gpio_clr_len(self); `}
92 fun set_eds
`{ bcm2835_gpio_set_eds(self); `}
93 fun eds: Bool `{ return bcm2835_gpio_eds(self); `}
95 # Return input on pin, true for high and false for low
96 fun lev
: Bool `{ return bcm2835_gpio_lev(self); `}
99 extern class FunctionSelect `{ bcm2835FunctionSelect `}
101 new inpt
`{ return BCM2835_GPIO_FSEL_INPT; `}
104 new outp `{ return BCM2835_GPIO_FSEL_OUTP; `}
106 new alt0
`{ return BCM2835_GPIO_FSEL_ALT0; `}
107 new alt1 `{ return BCM2835_GPIO_FSEL_ALT1; `}
108 new alt2
`{ return BCM2835_GPIO_FSEL_ALT2; `}
109 new alt3 `{ return BCM2835_GPIO_FSEL_ALT3; `}
110 new alt4
`{ return BCM2835_GPIO_FSEL_ALT4; `}
111 new alt5 `{ return BCM2835_GPIO_FSEL_ALT5; `}
112 new mask
`{ return BCM2835_GPIO_FSEL_MASK; `}
115 extern class PUDControl `{ bcm2835PUDControl `}
116 new off
`{ return BCM2835_GPIO_PUD_OFF; `}
117 new down `{ return BCM2835_GPIO_PUD_DOWN; `}
118 new up
`{ return BCM2835_GPIO_PUD_UP; `}
122 fun bcm2835_delay `{ bcm2835_delay(self); `}
123 fun bcm2835_delay_micros
`{ bcm2835_delayMicroseconds(self); `}
132 # returns '<', '>' or null accoring to rotation or lack thereof
133 fun update: nullable Char
135 var new_a = pin_a.lev
136 var new_b = pin_b.lev
139 if new_a != old_a or new_b != old_b then
140 if not old_a and not old_b then
142 if not new_a and new_b then
144 else if new_a and not new_b then
147 else if old_a and old_b then
149 if not new_a and new_b then
151 else if new_a and not new_b then
164 # Hitachi HD44780 or similar 2-4 lines LCD displays
173 var ds = new Array[RPiPin]
176 fun flag_clear_display: Int do return 1
177 fun flag_return_home: Int do return 2
178 fun flag_entry_mode_set: Int do return 4
179 fun flag_display_control: Int do return 8
180 fun flag_cursor_shift: Int do return 16
181 fun flag_function_set: Int do return 32
182 fun flag_set_cgram_addr: Int do return 64
183 fun flag_set_ggram_addr: Int do return 128
186 fun flag_entry_right: Int do return 0
187 fun flag_entry_left: Int do return 2
188 fun flag_entry_shift_increment: Int do return 1
189 fun flag_entry_shift_decrement: Int do return 0
192 fun flag_display_on: Int do return 4
193 fun flag_display_off: Int do return 0
194 fun flag_cursor_on: Int do return 2
195 fun flag_cursor_off: Int do return 0
196 fun flag_blink_on: Int do return 1
197 fun flag_blink_off: Int do return 0
199 # display/cursor shift
200 fun flag_display_move: Int do return 8
201 fun flag_cursor_move: Int do return 0
202 fun flag_move_right: Int do return 4
203 fun flag_move_left: Int do return 0
206 fun flag_8bit_mode: Int do return 16
207 fun flag_4bit_mode: Int do return 0
208 fun flag_2_lines: Int do return 8
209 fun flag_1_line: Int do return 0
210 fun flag_5x10_dots: Int do return 4
211 fun flag_5x8_dots: Int do return 0
213 # last text displayed
214 private var last_text: nullable String = null
216 fun function_set(bits, lines, dots_wide: Int)
218 var fs = flag_function_set
221 else if bits != 4 then abort
225 else if lines != 1 then abort
227 if dots_wide == 10 then
229 else if dots_wide != 8 then abort
234 fun display_control(on, cursor, blink: Bool)
236 var fs = flag_display_control
238 fs |= if on then flag_display_on else flag_display_off
240 fs |= if cursor then flag_cursor_on else flag_cursor_off
242 fs |= if blink then flag_blink_on else flag_blink_off
247 fun entry_mode(left, incr: Bool)
249 var fs = flag_entry_mode_set
251 fs |= if left then flag_entry_left else flag_entry_right
253 fs |= if incr then flag_entry_shift_increment else flag_entry_shift_decrement
262 rs.fsel = new FunctionSelect.outp
263 en.fsel = new FunctionSelect.outp
264 d4.fsel = new FunctionSelect.outp
265 d5.fsel = new FunctionSelect.outp
266 d6.fsel = new FunctionSelect.outp
267 d7.fsel = new FunctionSelect.outp
272 # wait 20ms for power up
275 write_4bits(true,true,false,false)
280 write_4bits(true,true,false,false)
285 write_4bits(true,true,false,false)
288 200.bcm2835_delay_micros
290 write_4bits(false,true,false,false)
298 function_set(4, 2, 8)
302 display_control(true, true, true)
307 # set cursor move direction
315 entry_mode(true, true)
322 rs.fsel = new FunctionSelect.outp
323 en.fsel = new FunctionSelect.outp
324 d4.fsel = new FunctionSelect.outp
325 d5.fsel = new FunctionSelect.outp
326 d6.fsel = new FunctionSelect.outp
327 d7.fsel = new FunctionSelect.outp
332 write(true, "33".to_hex) # init
333 write(true, "32".to_hex) # init
334 write(true, "28".to_hex) # 2 lines, 5x7
335 write(true, "0C".to_hex) # hide cursor
336 write(true, "06".to_hex) # cursor move right
337 write(true, "04".to_hex) # turn on display
338 write(true, "01".to_hex) # clear display
341 fun write_4_bits(v: Int)
343 var lb = once [1,2,4,8]
353 fun write_4bits(a,b,c,d:Bool)
365 1.bcm2835_delay_micros
367 100.bcm2835_delay_micros
369 1.bcm2835_delay_micros
372 fun write(is_cmd: Bool, cmd: Int)
378 var hb = once [16,32,64,128]
393 200.bcm2835_delay_micros
397 var lb = once [1,2,4,8]
412 200.bcm2835_delay_micros
430 # do not redraw the samething
431 var last_text = last_text
432 if last_text != null and last_text == v then return
439 # FIXME, this should work
440 #write(true, "C0".to_hex)
441 # instead we use the following which may not be portable
443 for s in [count..40[ do write(false, ' '.code_point)
446 write(false, c.code_point)
455 # Component for any kind of buttons or switches
459 init (pin: RPiPin, pud: PUDControl)
462 pin.fsel = new FunctionSelect.inpt
466 fun is_down: Bool do return pin.lev
468 var last_down: nullable Bool = null
470 # Returns true is state (is_down) changed since last call to `changed
`
474 var last_down = last_down
475 if last_down == null then
478 else if last_down != now then
486 var pins: Sequence[RPiPin]
489 init (delay: Int, a, b, c, d: RPiPin)
494 for p in pins do p.fsel = new FunctionSelect.outp
497 fun forward(steps: Int)
499 for s in [0..steps[ do
500 set(true, false, false, false)
502 set(true, true, false, false)
504 set(false, true, false, false)
506 set(false, true, true, false)
508 set(false, false, true, false)
510 set(false, false, true, true)
512 set(false, false, false, true)
514 set(true, false, false, true)
519 fun backwards(steps: Int)
521 for s in [0..steps[ do
522 set(true, false, false, true)
524 set(false, false, false, true)
526 set(false, false, true, true)
528 set(false, false, true, false)
530 set(false, true, true, false)
532 set(false, true, false, false)
534 set(true, true, false, false)
536 set(true, false, false, false)
541 fun release do set(false, false, false, false)
543 protected fun set(a, b, c, d: Bool)
545 var bits = new Array[Bool].with_items(a, b, c, d)
547 for i in [0..4[ do pins[i].write(bits[i])
554 fun buzz(delay: Float, times: Int)
558 var delay_i = (delay*1000.0).to_i
559 for i in [0..times[ do
561 delay_i.bcm2835_delay_micros
563 delay_i.bcm2835_delay_micros