A simple Lwt server for delivering the messages to the LCD
This commit is contained in:
parent
feb2e218dc
commit
c2ced8a13c
9
_oasis
9
_oasis
|
@ -24,3 +24,12 @@ Executable "adafruit-lcd-example"
|
||||||
BuildTools: ocamlbuild
|
BuildTools: ocamlbuild
|
||||||
MainIs: lcd_example.ml
|
MainIs: lcd_example.ml
|
||||||
BuildDepends: WiringPi,unix
|
BuildDepends: WiringPi,unix
|
||||||
|
|
||||||
|
Executable "adafruit-lcd-server"
|
||||||
|
CompiledObject: native
|
||||||
|
Path: examples/
|
||||||
|
BuildTools: ocamlbuild
|
||||||
|
MainIs: lcd_lwt.ml
|
||||||
|
BuildDepends: WiringPi,unix,lwt,lwt.unix,threads
|
||||||
|
CCLib: -lwiringPi
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
(** An example with Adafruit character LCD, HD44780. *)
|
||||||
|
open Gpio3
|
||||||
|
open Lcd
|
||||||
|
open Lwt
|
||||||
|
|
||||||
|
let lcd = {
|
||||||
|
columns = 16;
|
||||||
|
rows = 2;
|
||||||
|
rs = GPIO20;
|
||||||
|
en = GPIO16;
|
||||||
|
d4 = GPIO19;
|
||||||
|
d5 = GPIO5;
|
||||||
|
d6 = GPIO11;
|
||||||
|
d7 = GPIO10;
|
||||||
|
}
|
||||||
|
|
||||||
|
(** A nicer abstraction *)
|
||||||
|
module Cursor = struct
|
||||||
|
type t = { x: int; y: int; visible: bool; blink: bool; _lcd: mono_lcd }
|
||||||
|
|
||||||
|
(** Creates a new cursor at the position (0,0) *)
|
||||||
|
let of_lcd lcd =
|
||||||
|
set_position lcd 0 0;
|
||||||
|
{ x = 0; y = 0; visible = false; blink = false; _lcd = lcd }
|
||||||
|
|
||||||
|
(** Explicitly set the position of the cursor. The arguments will be
|
||||||
|
taken modulo the size of the LCD. *)
|
||||||
|
let set_position x y cur =
|
||||||
|
let col = x mod cur._lcd.columns in
|
||||||
|
let row = y mod cur._lcd.rows in
|
||||||
|
set_position cur._lcd col row;
|
||||||
|
{ cur with x = col; y = row }
|
||||||
|
|
||||||
|
(** Whether to display the cursor *)
|
||||||
|
let set_visible flag cur =
|
||||||
|
let _blinkon = if cur.blink then _lcd_blinkon else _lcd_blinkoff in
|
||||||
|
let _cursoron = if flag then _lcd_cursoron else _lcd_cursoroff in
|
||||||
|
let displayctrl = _lcd_displayon lor _cursoron lor _blinkon in
|
||||||
|
write8_unsafe lcd (displayctrl lor _lcd_displaycontrol);
|
||||||
|
{ cur with visible = flag }
|
||||||
|
|
||||||
|
(** Whether the cursor is blinking *)
|
||||||
|
let set_blink flag cur =
|
||||||
|
let _blinkon = if flag then _lcd_blinkon else _lcd_blinkoff in
|
||||||
|
let _cursoron = if cur.visible then _lcd_cursoron else _lcd_cursoroff in
|
||||||
|
let displayctrl = _lcd_displayon lor _cursoron lor _blinkon in
|
||||||
|
write8_unsafe lcd (displayctrl lor _lcd_displaycontrol);
|
||||||
|
{ cur with blink = flag }
|
||||||
|
|
||||||
|
(** Try writing a character, optionally with wrapping. *)
|
||||||
|
let write_char wrapping v cur =
|
||||||
|
write8 cur._lcd ~char_mode:true v;
|
||||||
|
let col = cur.x + 1 in
|
||||||
|
if not wrapping || col < cur._lcd.columns
|
||||||
|
then { cur with x = col }
|
||||||
|
else let row = cur.y + 1 in
|
||||||
|
let col = 0 in
|
||||||
|
(* set_position should do the wrapping for us *)
|
||||||
|
set_position col row cur
|
||||||
|
|
||||||
|
let write_bytes wrapping bts cur =
|
||||||
|
let f cur chr =
|
||||||
|
if chr = '\n'
|
||||||
|
then set_position 0 (cur.y + 1) cur
|
||||||
|
else if chr = '\r'
|
||||||
|
then set_position 0 cur.y cur
|
||||||
|
else write_char wrapping chr cur in
|
||||||
|
Seq.fold_left f cur (Bytes.to_seq bts)
|
||||||
|
|
||||||
|
let write_string ?(wrap=false) str cur = write_bytes wrap (Bytes.of_string str) cur
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
(** A useful combinator for the functions from the [Cursor] module *)
|
||||||
|
let (|>) (m : Cursor.t) (f : Cursor.t -> 'b) = f m
|
||||||
|
|
||||||
|
(** Display two lines without wrapping *)
|
||||||
|
let display_lines l1 l2 =
|
||||||
|
let col_shift = 3 in
|
||||||
|
let maxwidth = int_of_float (float_of_int lcd.columns *. 2.5) - col_shift in
|
||||||
|
let trunc str =
|
||||||
|
let n = min maxwidth (String.length str) in
|
||||||
|
String.sub str 0 n
|
||||||
|
in
|
||||||
|
let open Cursor in
|
||||||
|
clear lcd;
|
||||||
|
of_lcd lcd
|
||||||
|
|> set_visible false
|
||||||
|
|> set_blink false
|
||||||
|
|> set_position col_shift 0
|
||||||
|
|> write_string (trunc l1) ~wrap:false
|
||||||
|
|> set_position col_shift 1
|
||||||
|
|> write_string (trunc l2) ~wrap:false
|
||||||
|
|
||||||
|
(** Scrolling thread *)
|
||||||
|
|
||||||
|
let rec scroll lcd sleep_for : unit Lwt.t =
|
||||||
|
shift_left lcd;
|
||||||
|
Lwt_unix.sleep sleep_for >>= fun () ->
|
||||||
|
scroll lcd sleep_for
|
||||||
|
|
||||||
|
|
||||||
|
(** Networking stuff *)
|
||||||
|
|
||||||
|
let create_socket () =
|
||||||
|
let open Lwt_unix in
|
||||||
|
let sock = socket PF_INET SOCK_STREAM 0 in
|
||||||
|
(* let bind_addr = Unix.inet_addr_loopback in *)
|
||||||
|
gethostbyname "balthasar.local" >>= fun bind_addr ->
|
||||||
|
let bind_addr = bind_addr.h_addr_list.(0) in
|
||||||
|
bind sock @@ ADDR_INET(bind_addr, 8080) >>= fun () ->
|
||||||
|
listen sock 10;
|
||||||
|
return sock
|
||||||
|
|
||||||
|
let rec handle_message ic oc () =
|
||||||
|
Lwt_io.read_line_opt ic >>= fun line1 ->
|
||||||
|
Lwt_io.read_line_opt ic >>= fun line2 ->
|
||||||
|
match line1,line2 with
|
||||||
|
| Some l1, Some l2 ->
|
||||||
|
Lwt_io.printl "Recieved the following message:" >>= fun () ->
|
||||||
|
Lwt_io.printl l1 >>= fun () ->
|
||||||
|
Lwt_io.printl l2 >>= fun () ->
|
||||||
|
Lwt.async (fun () -> Lwt_io.close oc);
|
||||||
|
ignore (display_lines l1 l2);
|
||||||
|
return ()
|
||||||
|
| _,_ -> return ()
|
||||||
|
|
||||||
|
let handle_connection conn =
|
||||||
|
let fd, _ = conn in
|
||||||
|
let ic = Lwt_io.of_fd Lwt_io.Input fd in
|
||||||
|
let oc = Lwt_io.of_fd Lwt_io.Output fd in
|
||||||
|
Lwt.on_failure (handle_message ic oc ())
|
||||||
|
(fun e -> Printf.printf "Error in `handle_message': %s\n" (Printexc.to_string e));
|
||||||
|
return ()
|
||||||
|
|
||||||
|
let create_server sock =
|
||||||
|
let rec serve () =
|
||||||
|
Lwt_unix.accept sock >>= handle_connection >>= serve
|
||||||
|
in serve
|
||||||
|
|
||||||
|
let main () =
|
||||||
|
Lwt.async (fun () -> scroll lcd 0.7);
|
||||||
|
create_socket () >>= fun sock ->
|
||||||
|
create_server sock ()
|
||||||
|
|
||||||
|
|
||||||
|
let _ =
|
||||||
|
setup lcd;
|
||||||
|
clear lcd;
|
||||||
|
ignore (display_lines "Hello, " "world!");
|
||||||
|
Lwt_main.run @@ main ()
|
||||||
|
|
Loading…
Reference in New Issue