commit 59b417485fba57b70cbcfe8c3191a5d4b5e9e963 Author: Tobias Bora Date: Tue Dec 3 10:49:04 2013 +0100 First commit, a first version of wiringPiOcaml works, and the shift register can be used ! diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f821564 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CC=ocamlc +OPT=-custom + +MAIN=sapin_noel.ml +SOURCES=wiringPiOcaml_stub.c wiringPiOcaml.ml shiftReg.ml +PACKAGES=unix parmap + +OBJECTS=$(SOURCES) +OUTPUT=$(MAIN:.ml=.bin) + + +all: $(OBJECTS) + $(CC) $(OPT) -cclib -lwiringPi unix.cma $(SOURCES) $(MAIN) -o $(OUTPUT) + +clean: + rm -f *.cmo *.cmi *.cmx + diff --git a/sapin_noel.bin b/sapin_noel.bin new file mode 100755 index 0000000..b3bc321 Binary files /dev/null and b/sapin_noel.bin differ diff --git a/sapin_noel.ml b/sapin_noel.ml new file mode 100644 index 0000000..38cba77 --- /dev/null +++ b/sapin_noel.ml @@ -0,0 +1,33 @@ +open WiringPiOcaml;; +open ShiftReg;; + +let _ = + (* On choisit le mode d'affichage Phys *) + setupPhys (); + (* reg : pin_value = p_v, pin_shift = p_s, pin_apply = p_a *) + (* On crée le register *) + let reg = (11,13,15) in + (* On initialise *) + let leds = initRegister reg ~nb_reg:1 in + (* On boucle pour afficher les leds unes par unes *) + while true do + + for k = 0 to (Array.length leds) - 1 do + leds.(k) <- true; + applyReg reg leds; + delay 100; + leds.(k) <- false + done; + for k = (Array.length leds) - 2 downto 0 do + leds.(k) <- true; + applyReg reg leds; + delay 100; + leds.(k) <- false + done; + lightLeds leds; + applyReg reg leds; + Unix.sleep 1; + clearLeds leds; + done + +;; diff --git a/shiftReg.bin b/shiftReg.bin new file mode 100755 index 0000000..a05060c Binary files /dev/null and b/shiftReg.bin differ diff --git a/shiftReg.ml b/shiftReg.ml new file mode 100644 index 0000000..6dd6d02 --- /dev/null +++ b/shiftReg.ml @@ -0,0 +1,40 @@ +(** This module allow to communicate with a shift-register **) + +(* Source : + - http://blog.idleman.fr/raspberry-pi-20-creer-un-tableau-de-bord-connect-au-net/ + - http://www.onsemi.com/pub_link/Collateral/MC74HC595A-D.PDF +*) +open WiringPiOcaml +(** reg : (pin_value = p_v, pin_shift = p_s, pin_apply = p_a). It is + used to contain the needed input **) +type reg = int * int * int;; + +(** The first thing to do is setupPhys (). This function put in OUTPUT + mode the outputs and return back a bool array which represent the output of registers (begining with the first LED of the first shift register) **) +let initRegister ?nb_reg:(nb_reg = 1) reg = + let (p_v, p_s, p_a) = reg in + pinMode p_v 1; (* mode output *) + pinMode p_s 1; + pinMode p_a 1; + Array.make (8*nb_reg) false (* return back an array for all pieces *) + +let write pin value = digitalWrite pin (if value then 1 else 0) + +(** This function apply all modifications to the register **) +let applyReg reg leds = + let (p_v, p_s, p_a) = reg in + write p_a false; + for i = (Array.length leds) - 1 downto 0 do + write p_s false; + write p_v leds.(i); + write p_s true; + done; + write p_a true + + +(** Don't forget to apply it with applyReg after **) +let clearLeds leds = + Array.iteri (fun i x -> (leds.(i) <- false)) leds +let lightLeds leds = + Array.iteri (fun i x -> (leds.(i) <- true)) leds + diff --git a/wiringPiOcaml.bin b/wiringPiOcaml.bin new file mode 100755 index 0000000..6813e25 Binary files /dev/null and b/wiringPiOcaml.bin differ diff --git a/wiringPiOcaml.ml b/wiringPiOcaml.ml new file mode 100644 index 0000000..f305ab5 --- /dev/null +++ b/wiringPiOcaml.ml @@ -0,0 +1,67 @@ +(** This module is useful to communicate with the GPIO ports of a raspberry. + It uses the wiringPi library : http://wiringpi.com/ **) + +(* Test function *) +external test_hello_world : unit -> unit = "caml_hello" + +(* Use it at the very beginning to choose the numeroting mode *) +external setup : unit -> int = "caml_wiringPiSetup" +external setupGio : unit -> int = "caml_wiringPiSetupGpio" +external setupPhys : unit -> int = "caml_wiringPiSetupPhys" +external setupSys : unit -> int = "caml_wiringPiSetupSys" + +(* ########## Write on the device ########## *) +(* This sets the mode of a pin to either INPUT (= 0), OUTPUT (= 1), PWM_OUTPUT (= 2) or GPIO_CLOCK (= 3). Note that only wiringPi pin 1 (BCM_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM_GPIO 4) supports CLOCK output modes. *) +external pinMode : int -> int -> unit = "caml_pinMode" + +(* This sets the pull-up or pull-down resistor mode on the given pin, which should be set as an input. *) +external pullUpDnControl : int -> int -> unit = "caml_pullUpDnControl" + +(* Writes the value HIGH or LOW (1 or 0) to the given pin which must have been previously set as an output. *) +external digitalWrite : int -> int -> unit = "caml_digitalWrite" + +(* Writes the value to the PWM register for the given pin. The Raspberry Pi has one on-board PWM pin, pin 1 (BMC_GPIO 18, Phys 12) and the range is 0-1024. Other PWM devices may have other PWM ranges *) +external pwmWrite : int -> int -> unit = "caml_pwmWrite" + +(* This function returns the value read at the given pin. It will be HIGH or LOW (1 or 0) depending on the logic level at the pin. *) +external digitalRead : int -> int = "caml_digitalRead" +external digitalWriteByte : int -> unit = "caml_digitalWriteByte" + + +(* ########## Timing ########## *) +(* Use it to wait a few ms or µs. If you want to wait for several + secondes, use Unix.sleep. *) +external delay : int -> unit = "caml_delay" (* wait n ms *) +external delayMicroseconds : int -> unit = "caml_delayMicroseconds" (* wait n µs *) + +(* This returns a number representing the number if ms/µs since your program called one of the wiringPiSetup functions. *) +external millis : unit -> int = "caml_millis" +external micros : unit -> int = "caml_micros" + + +(* ################# Name of pins : ################# *) +(* +----------+-Rev2-+------+--------+------+-------+ *) +(* | wiringPi | GPIO | Phys | Name | Mode | Value | *) +(* +----------+------+------+--------+------+-------+ *) +(* | 0 | 17 | 11 | GPIO 0 | IN | Low | *) +(* | 1 | 18 | 12 | GPIO 1 | IN | High | *) +(* | 2 | 27 | 13 | GPIO 2 | IN | High | *) +(* | 3 | 22 | 15 | GPIO 3 | IN | High | *) +(* | 4 | 23 | 16 | GPIO 4 | IN | Low | *) +(* | 5 | 24 | 18 | GPIO 5 | IN | Low | *) +(* | 6 | 25 | 22 | GPIO 6 | IN | High | *) +(* | 7 | 4 | 7 | GPIO 7 | IN | High | *) +(* | 8 | 2 | 3 | SDA | IN | High | *) +(* | 9 | 3 | 5 | SCL | IN | High | *) +(* | 10 | 8 | 24 | CE0 | IN | High | *) +(* | 11 | 7 | 26 | CE1 | IN | Low | *) +(* | 12 | 10 | 19 | MOSI | IN | High | *) +(* | 13 | 9 | 21 | MISO | IN | High | *) +(* | 14 | 11 | 23 | SCLK | IN | High | *) +(* | 15 | 14 | 8 | TxD | ALT0 | High | *) +(* | 16 | 15 | 10 | RxD | ALT0 | High | *) +(* | 17 | 28 | 3 | GPIO 8 | OUT | High | *) +(* | 18 | 29 | 4 | GPIO 9 | IN | Low | *) +(* | 19 | 30 | 5 | GPIO10 | IN | Low | *) +(* | 20 | 31 | 6 | GPIO11 | IN | Low | *) +(* +----------+------+------+--------+------+-------+ *) diff --git a/wiringPiOcaml_stub.c b/wiringPiOcaml_stub.c new file mode 100644 index 0000000..279c208 --- /dev/null +++ b/wiringPiOcaml_stub.c @@ -0,0 +1,138 @@ +/* ******************************************** + This file make the link between wiringPi + and wiringPiOcaml + ******************************************** */ + +#include +#include +#include +#include +#include + +CAMLprim +value caml_hello(value unit) { + CAMLparam1(unit); + printf("Hello world!\n"); + CAMLreturn(Val_unit); +} + +CAMLprim +value caml_wiringPiSetup(value unit) +{ + CAMLparam1(unit); + CAMLreturn(Val_int(wiringPiSetup())); +} + +CAMLprim +value caml_wiringPiSetupGpio(value unit) +{ + CAMLparam1(unit); + CAMLreturn(Val_int(wiringPiSetupGpio())); +} + +CAMLprim +value caml_wiringPiSetupPhys(value unit) +{ + CAMLparam1(unit); + CAMLreturn(Val_int(wiringPiSetupPhys())); +} + +CAMLprim +value caml_wiringPiSetupSys(value unit) +{ + CAMLparam1(unit); + CAMLreturn(Val_int(wiringPiSetupSys())); +} + +// Core functions + +CAMLprim +value caml_pinMode(value pin, value mode) +{ + CAMLparam2(pin, mode); + pinMode(Int_val(pin), Int_val(mode)); + CAMLreturn(Val_unit); +} + +CAMLprim +value caml_pullUpDnControl(value pin, value pud) +{ + CAMLparam2(pin, pud); + pullUpDnControl(Int_val(pin), Int_val(pin)); + CAMLreturn(Val_unit); +} + +CAMLprim +value caml_digitalWrite(value pin, value value_p) +{ + CAMLparam2(pin, value_p); + digitalWrite(Int_val(pin), Int_val(value_p)); + CAMLreturn(Val_unit); +} + +CAMLprim +value caml_pwmWrite(value pin, value value_p) +{ + CAMLparam2(pin, value_p); + pwmWrite(Int_val(pin), Int_val(value_p)); + CAMLreturn(Val_unit); +} + +CAMLprim +value caml_digitalRead(value pin) +{ + CAMLparam1(pin); + CAMLreturn(Val_int(digitalRead(Int_val(pin)))); +} + +// AnalogRead and AnalogWrite needs to be added (module must be added) + +// Raspberry Pi Specifics + +CAMLprim +value caml_digitalWriteByte(value value_p) +{ + CAMLparam1(value_p); + digitalWriteByte(Int_val(value_p)); + CAMLreturn(Val_unit); +} + +// Others can be added... + +// Shift Library + +// Timing + +/* This returns a number representing the number if milliseconds since your program called one of the wiringPiSetup functions. */ +CAMLprim +value caml_millis(value unit) +{ + CAMLparam1(unit); + CAMLreturn(Val_int(millis())); +} + +/* This returns a number representing the number of microseconds since your program called one of the wiringPiSetup functions. */ +CAMLprim +value caml_micros(value unit) +{ + CAMLparam1(unit); + CAMLreturn(Val_int(micros())); +} + +/* This causes program execution to pause for at least howLong milliseconds. Due to the multi-tasking nature of Linux it could be longer. */ +CAMLprim +value caml_delay(value howLong) +{ + CAMLparam1(howLong); + delay(Int_val(howLong)); + CAMLreturn(Val_unit); +} + +/* This causes program execution to pause for at least howLong microseconds. Due to the multi-tasking nature of Linux it could be longer. Delays under 100 microseconds are timed using a hard-coded loop continually polling the system time, Delays over 100 microseconds are done using the system nanosleep() function – You may need to consider the implications of very short delays on the overall performance of the system, especially if using threads. */ +CAMLprim +value caml_delayMicroseconds(value howLong) +{ + CAMLparam1(howLong); + delayMicroseconds(Int_val(howLong)); + CAMLreturn(Val_unit); +}