mirror of
				https://github.com/co-dan/ocaml-wiringpi/
				synced 2025-11-03 22:23:51 +01:00 
			
		
		
		
	A simple Lwt server for delivering the messages to the LCD
This commit is contained in:
		
							
								
								
									
										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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										152
									
								
								examples/lcd_lwt.ml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								examples/lcd_lwt.ml
									
									
									
									
									
										Normal file
									
								
							@@ -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 ()
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
		Reference in New Issue
	
	Block a user