contrib: added wiringPi wrapper
authorAlexandre Terrasa <alexandre@moz-code.org>
Sun, 29 Sep 2013 04:35:20 +0000 (00:35 -0400)
committerAlexandre Terrasa <alexandre@moz-code.org>
Sun, 29 Sep 2013 04:35:20 +0000 (00:35 -0400)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

contrib/wiringPi/README.md [new file with mode: 0644]
contrib/wiringPi/examples/blink.nit [new file with mode: 0644]
contrib/wiringPi/examples/read.nit [new file with mode: 0644]
contrib/wiringPi/examples/shift.nit [new file with mode: 0644]
contrib/wiringPi/lib/wiringPi.nit [new file with mode: 0644]

diff --git a/contrib/wiringPi/README.md b/contrib/wiringPi/README.md
new file mode 100644 (file)
index 0000000..1085abb
--- /dev/null
@@ -0,0 +1,54 @@
+# wiringPi nit wrapper
+
+## Installation
+
+You need to install the [wiringPi library](http://wiringpi.com/). Refer to [download and install](http://wiringpi.com/download-and-install/) manual.
+
+## Compiling
+
+Link to the library must be passed to nit compiler:
+
+       nitc myprogram.nit --cc-lib-name wiringPi
+
+## Usage
+
+You first need to initialize the wiringPi library using a setup methods.
+
+Setup methods are:
+
+* `wiringPi_setup`: This initialises wiringPi and assumes that the calling program is going to be using the wiringPi pin numbering scheme;
+* `wiringPi_setup_gpio`: Same as wiringPi_setup, however it allows the calling programs to use the Broadcom GPIO pin numbers directly with no re-mapping;
+* `wiringPi_setup_phys`: Identical to wiringPi_setup, however it allows the calling programs to use the physical pin numbers on the P1 connector only;
+* `wiringPi_setup_sys`: This initialises wiringPi but uses the /sys/class/gpio interface rather than accessing the hardware directly;
+
+For example:
+
+       # init wiringPi lib with gpio output
+       wiringPi_set_gpio
+
+Then you can refer to a GPIO Pin using its id:
+
+       var pin = new RPIPin(23)
+
+Before read or write a value on a pin you need to set its mode.
+
+Modes are:
+
+* INPUT
+* OUTPUT
+* PWM_OUTPUT
+* GPIO_CLOCK
+
+Note that only wiringPi pin 1 (BCM\_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM\_GPIO 4) supports CLOCK output modes.
+
+       pin.mode(new RPIPinMode.output_mode)
+
+You can then `write` or `read` a value from the pin:
+
+       pin.write(true)
+       pin.read
+
+## Copyrigth
+
+The wiringPi library is released under [GNU LGPLv3](http://www.gnu.org/copyleft/lesser.html) licence.
+
diff --git a/contrib/wiringPi/examples/blink.nit b/contrib/wiringPi/examples/blink.nit
new file mode 100644 (file)
index 0000000..b14ded6
--- /dev/null
@@ -0,0 +1,37 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexandre Terrasa <alexandre@moz-code.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import wiringPi
+
+if args.length != 1 then
+       print "usage: blink pin_id"
+       exit(1)
+end
+
+# init wiringPi lib
+wiringPi_setup
+
+# init the pin
+var id = args.first.to_i
+var pin = new RPiPin(id)
+pin.mode(new RPiPinMode.output_mode)
+
+# blink
+loop
+       pin.write(true)
+       nanosleep(1, 0)
+       pin.write(false)
+       nanosleep(1, 0)
+end
diff --git a/contrib/wiringPi/examples/read.nit b/contrib/wiringPi/examples/read.nit
new file mode 100644 (file)
index 0000000..1ea366f
--- /dev/null
@@ -0,0 +1,35 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexandre Terrasa <alexandre@moz-code.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import wiringPi
+
+if args.length != 1 then
+       print "usage: blink pin_id"
+       exit(1)
+end
+
+# init wiringPi lib
+wiringPi_setup
+
+# init the pin
+var id = args.first.to_i
+var pin = new RPiPin(id)
+pin.mode(new RPiPinMode.input_mode)
+
+# listen
+loop
+       print pin.read
+       nanosleep(1, 0)
+end
diff --git a/contrib/wiringPi/examples/shift.nit b/contrib/wiringPi/examples/shift.nit
new file mode 100644 (file)
index 0000000..4038d28
--- /dev/null
@@ -0,0 +1,51 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexandre Terrasa <alexandre@moz-code.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import wiringPi
+
+if args.is_empty or args.length > 2 then
+       print "usage:"
+       print "\tshift <register> <state>"
+       print "\tshift clear"
+       print "\tshift all"
+       exit(1)
+end
+
+# init wiringPi lib
+wiringPi_setup
+
+# register layout and pin numbering
+var nb_pins = 8
+var ser_pin = 7
+var rclk_pin = 6
+var srclk_pin = 5
+var sr = new SR595(nb_pins, ser_pin, rclk_pin, srclk_pin)
+
+# set all registers to 0
+if args.first == "clear" then
+       sr.clear_registers
+# set all registers to 1
+else if args.first == "all" then
+       var regs = new Array[Bool].filled_with(true, nb_pins)
+       sr.clear_registers
+       sr.write_all(regs)
+# set specified register to specified value
+else
+       if args[1].to_i == 0 then
+               sr.write(args.first.to_i, false)
+       else
+               sr.write(args.first.to_i, true)
+       end
+end
diff --git a/contrib/wiringPi/lib/wiringPi.nit b/contrib/wiringPi/lib/wiringPi.nit
new file mode 100644 (file)
index 0000000..2852256
--- /dev/null
@@ -0,0 +1,166 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexandre Terrasa <alexandre@moz-code.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Nit wrapping of the wiringPi library [http://wiringpi.com/]
+# WiringPi is an Arduino wiring-like library written in C
+# and released under the GNU LGPLv3 license which is usable
+# from C and C++ and many other languages with suitable wrappers
+module wiringPi
+
+in "C Header" `{
+       #include <wiringPi.h>
+
+       typedef struct {
+               int id;
+       } CRPiPin;
+`}
+
+
+redef class Object
+       # This initialises wiringPi and assumes that the calling program is
+       # going to be using the wiringPi pin numbering scheme.
+       fun wiringPi_setup `{ wiringPiSetup(); `}
+       # Same as wiringPi_setup, however it allows the calling programs to
+       # use the Broadcom GPIO pin numbers directly with no re-mapping.
+       fun wiringPi_setup_gpio `{ wiringPiSetupGpio(); `}
+       # Identical to wiringPi_setup, however it allows the calling
+       # programs to use the physical pin numbers on the P1 connector only.
+       fun wiringPi_setup_phys `{ wiringPiSetupPhys(); `}
+       # This initialises wiringPi but uses the /sys/class/gpio interface
+       # rather than accessing the hardware directly.
+       fun wiringPi_setup_sys `{ wiringPiSetupSys(); `}
+end
+
+# A Raspberry Pi GPIO Pin
+extern class RPiPin `{ CRPiPin *`}
+       new (id: Int) `{
+               CRPiPin *pin = malloc( sizeof(CRPiPin) );
+               pin->id = id;
+               return pin;
+       `}
+
+       # The pin `id` depends on wiringPi setup used
+       fun id: Int `{ return recv->id; `}
+
+       # Sets the mode of the pin
+       fun mode(mode: RPiPinMode) `{ pinMode(recv->id, mode); `}
+
+       # This sets the pull-up or pull-down resistor mode on the given pin,
+       # which should be set as an input.
+       fun pullup_dncontrol(pud: PUDControl) `{ pullUpDnControl(recv->id, pud); `}
+
+       # Writes the value HIGH or LOW (true or false) to the given pin which must
+       # have been previously set as an output.
+       fun write(high: Bool) `{ digitalWrite(recv->id, high? HIGH: LOW); `}
+
+       # 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.
+       fun pwm_write(value: Int) `{ pwmWrite(recv->id, value); `}
+
+       # This function returns the value read at the given pin.
+       # It will be HIGH or LOW (true or false) depending on the logic level at the pin.
+       fun read: Bool `{ return digitalRead(recv->id) == HIGH? true: false; `}
+end
+
+# RPI Pin modes
+# Modes are:
+# * INPUT
+# * OUTPUT
+# * PWM_OUTPUT
+# * GPIO_CLOCK
+# Note that only wiringPi pin 1 (BCM_GPIO 18) supports PWM output
+# and only wiringPi pin 7 (BCM_GPIO 4) supports CLOCK output modes.
+extern class RPiPinMode `{ int `}
+       new input_mode `{ return INPUT; `}
+       new output_mode `{ return OUTPUT; `}
+       new pwm_mode `{ return PWM_OUTPUT; `}
+       new clock_mode `{ return GPIO_CLOCK; `}
+end
+
+# The BCM2835 has both pull-up an down internal resistors.
+# The parameter pud should be:
+# * PUD_OFF, (no pull up/down)
+# * PUD_DOWN (pull to ground)
+# * PUD_UP (pull to 3.3v)
+# The internal pull up/down resistors have a value of approximately
+# 50Kohms on the Raspberry Pi.
+extern class PUDControl `{ int `}
+       new off `{ return PUD_OFF; `}
+       new down `{ return PUD_DOWN; `}
+       new up `{ return PUD_UP; `}
+end
+
+# Abstraction a daisy chain of 74×595 shift registers
+class SR595
+       private var registers: Array[Bool]
+       private var nb_pins: Int
+       private var ser: RPiPin
+       private var rclk: RPiPin
+       private var srclk: RPiPin
+
+       # Initialize a new shift register chain
+       # `nb_pins`: number of pins available
+       # `ser_pin`: SER (serial) pin id
+       # `rclk_pin`: RCLK (register clock) pin id
+       # `srclk_pin`: SRCLK (serial clock) pin id
+       init(nb_pins, ser_pin, rclk_pin, srclk_pin: Int) do
+               # configure pin layout
+               self.nb_pins = nb_pins
+               self.ser = new RPiPin(7)
+               self.rclk = new RPiPin(6)
+               self.srclk = new RPiPin(5)
+               clear_registers
+               # enable output mode on shift register output
+               ser.mode(new RPiPinMode.output_mode)
+               rclk.mode(new RPiPinMode.output_mode)
+               srclk.mode(new RPiPinMode.output_mode)
+       end
+
+       # write 'state' on register 'reg'
+       fun write(reg: Int, state: Bool) do
+               registers[reg] = state
+               write_registers
+       end
+
+       # write all registers
+       fun write_all(regs: Array[Bool]) do
+               assert regs.length == nb_pins
+               registers = regs
+               write_registers
+       end
+
+       # clear all registers
+       fun clear_registers do
+               registers = new Array[Bool].filled_with(false, nb_pins)
+               write_registers
+       end
+
+       private fun write_registers do
+               rclk.write(false)
+               var i = registers.length - 1
+               while i >= 0 do
+                       var reg = registers[i]
+                       srclk.write(false)
+                       ser.write(reg)
+                       srclk.write(true)
+                       i -= 1
+               end
+               rclk.write(true)
+       end
+end
+