diff --git a/build b/build index ba31b7a..d74071e 100755 --- a/build +++ b/build @@ -104,6 +104,21 @@ install() { fi check_make_ok + echo + echo "WiringPi Devices Library" + cd ../devLib + $sudo $make uninstall + if [ x$1 = "xstatic" ]; then + $make static + check_make_ok + $sudo $make install-static + else + $make + check_make_ok + $sudo $make install + fi + check_make_ok + echo echo "WiringPi Devices Library" cd ../devLib @@ -135,6 +150,9 @@ install() { echo "" echo "NOTE: To compile programs with wiringPi, you need to add:" echo " -lwiringPi -wiringPiDev" + echo " to your compile line(s) To use the Gertboard, MaxDetect, etc." + echo " code (the devLib), you need to also add:" + echo " -lwiringPiDev" echo " to your compile line(s)." echo "" } @@ -159,8 +177,18 @@ clean() { cd ../gpio echo -n "gpio: " ; $make clean cd ../examples - echo -n "examples: " ; $make clean - cd .. + echo -n "Examples: " ; $make clean + cd Gertboard + echo -n "Gertboard: " ; $make clean + cd ../PiFace + echo -n "PiFace: " ; $make clean + cd ../q2w + echo -n "Quick2Wire: " ; $make clean + cd ../PiGlow + echo -n "PiGlow: " ; $make clean + cd ../scrollPhat + echo -n "scrollPhat: " ; $make clean + cd ../.. } if [ x$1 = "xclean" ]; then diff --git a/devLib/Makefile b/devLib/Makefile index 59a4cc8..6f1c800 100644 --- a/devLib/Makefile +++ b/devLib/Makefile @@ -47,11 +47,16 @@ LIBS = ############################################################################### -SRC = lcd128x64.c lcd.c +SRC = ds1302.c maxdetect.c piNes.c \ + gertboard.c piFace.c \ + lcd128x64.c lcd.c \ + scrollPhat.c \ + piGlow.c OBJ = $(SRC:.c=.o) -HEADERS = lcd128x64.h lcd.h +HEADERS = ds1302.h gertboard.h lcd128x64.h lcd.h maxdetect.h piFace.h piGlow.h piNes.h\ + scrollPhat.h all: $(DYNAMIC) @@ -117,5 +122,10 @@ depend: # DO NOT DELETE +ds1302.o: ds1302.h +maxdetect.o: maxdetect.h +piNes.o: piNes.h +gertboard.o: gertboard.h +piFace.o: piFace.h lcd128x64.o: font.h lcd128x64.h lcd.o: lcd.h diff --git a/devLib/ds1302.c b/devLib/ds1302.c new file mode 100644 index 0000000..cf64de7 --- /dev/null +++ b/devLib/ds1302.c @@ -0,0 +1,240 @@ +/* + * ds1302.c: + * Real Time clock + * + * Copyright (c) 2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include + +#include + +#include "ds1302.h" + +// Register defines + +#define RTC_SECS 0 +#define RTC_MINS 1 +#define RTC_HOURS 2 +#define RTC_DATE 3 +#define RTC_MONTH 4 +#define RTC_DAY 5 +#define RTC_YEAR 6 +#define RTC_WP 7 +#define RTC_TC 8 +#define RTC_BM 31 + + +// Locals + +static int dPin, cPin, sPin ; + +/* + * dsShiftIn: + * Shift a number in from the chip, LSB first. Note that the data is + * sampled on the trailing edge of the last clock, so it's valid immediately. + ********************************************************************************* + */ + +static unsigned int dsShiftIn (void) +{ + uint8_t value = 0 ; + int i ; + + pinMode (dPin, INPUT) ; delayMicroseconds (1) ; + + for (i = 0 ; i < 8 ; ++i) + { + value |= (digitalRead (dPin) << i) ; + digitalWrite (cPin, HIGH) ; delayMicroseconds (1) ; + digitalWrite (cPin, LOW) ; delayMicroseconds (1) ; + } + + return value; +} + + +/* + * dsShiftOut: + * A normal LSB-first shift-out, just slowed down a bit - the Pi is + * a bit faster than the chip can handle. + ********************************************************************************* + */ + +static void dsShiftOut (unsigned int data) +{ + int i ; + + pinMode (dPin, OUTPUT) ; + + for (i = 0 ; i < 8 ; ++i) + { + digitalWrite (dPin, data & (1 << i)) ; delayMicroseconds (1) ; + digitalWrite (cPin, HIGH) ; delayMicroseconds (1) ; + digitalWrite (cPin, LOW) ; delayMicroseconds (1) ; + } +} + + +/* + * ds1302regRead: ds1302regWrite: + * Read/Write a value to an RTC Register or RAM location on the chip + ********************************************************************************* + */ + +static unsigned int ds1302regRead (const int reg) +{ + unsigned int data ; + + digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ; + dsShiftOut (reg) ; + data = dsShiftIn () ; + digitalWrite (sPin, LOW) ; delayMicroseconds (1) ; + + return data ; +} + +static void ds1302regWrite (const int reg, const unsigned int data) +{ + digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ; + dsShiftOut (reg) ; + dsShiftOut (data) ; + digitalWrite (sPin, LOW) ; delayMicroseconds (1) ; +} + + +/* + * ds1302rtcWrite: ds1302rtcRead: + * Writes/Reads the data to/from the RTC register + ********************************************************************************* + */ + +unsigned int ds1302rtcRead (const int reg) +{ + return ds1302regRead (0x81 | ((reg & 0x1F) << 1)) ; +} + +void ds1302rtcWrite (int reg, unsigned int data) +{ + ds1302regWrite (0x80 | ((reg & 0x1F) << 1), data) ; +} + + +/* + * ds1302ramWrite: ds1302ramRead: + * Writes/Reads the data to/from the RTC register + ********************************************************************************* + */ + +unsigned int ds1302ramRead (const int addr) +{ + return ds1302regRead (0xC1 | ((addr & 0x1F) << 1)) ; +} + +void ds1302ramWrite (const int addr, const unsigned int data) +{ + ds1302regWrite ( 0xC0 | ((addr & 0x1F) << 1), data) ; +} + +/* + * ds1302clockRead: + * Read all 8 bytes of the clock in a single operation + ********************************************************************************* + */ + +void ds1302clockRead (int clockData [8]) +{ + int i ; + unsigned int regVal = 0x81 | ((RTC_BM & 0x1F) << 1) ; + + digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ; + + dsShiftOut (regVal) ; + for (i = 0 ; i < 8 ; ++i) + clockData [i] = dsShiftIn () ; + + digitalWrite (sPin, LOW) ; delayMicroseconds (1) ; +} + + +/* + * ds1302clockWrite: + * Write all 8 bytes of the clock in a single operation + ********************************************************************************* + */ + +void ds1302clockWrite (const int clockData [8]) +{ + int i ; + unsigned int regVal = 0x80 | ((RTC_BM & 0x1F) << 1) ; + + digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ; + + dsShiftOut (regVal) ; + for (i = 0 ; i < 8 ; ++i) + dsShiftOut (clockData [i]) ; + + digitalWrite (sPin, LOW) ; delayMicroseconds (1) ; +} + + +/* + * ds1302trickleCharge: + * Set the bits on the trickle charger. + * Probably best left alone... + ********************************************************************************* + */ + +void ds1302trickleCharge (const int diodes, const int resistors) +{ + if (diodes + resistors == 0) + ds1302rtcWrite (RTC_TC, 0x5C) ; // Disabled + else + ds1302rtcWrite (RTC_TC, 0xA0 | ((diodes & 3) << 2) | (resistors & 3)) ; +} + + + + +/* + * ds1302setup: + * Initialise the chip & remember the pins we're using + ********************************************************************************* + */ + +void ds1302setup (const int clockPin, const int dataPin, const int csPin) +{ + dPin = dataPin ; + cPin = clockPin ; + sPin = csPin ; + + digitalWrite (dPin, LOW) ; + digitalWrite (cPin, LOW) ; + digitalWrite (sPin, LOW) ; + + pinMode (dPin, OUTPUT) ; + pinMode (cPin, OUTPUT) ; + pinMode (sPin, OUTPUT) ; + + ds1302rtcWrite (RTC_WP, 0) ; // Remove write-protect +} diff --git a/devLib/ds1302.h b/devLib/ds1302.h new file mode 100644 index 0000000..e82b3ed --- /dev/null +++ b/devLib/ds1302.h @@ -0,0 +1,44 @@ +/* + * ds1302.h: + * Real Time clock + * + * Copyright (c) 2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned int ds1302rtcRead (const int reg) ; +extern void ds1302rtcWrite (const int reg, const unsigned int data) ; + +extern unsigned int ds1302ramRead (const int addr) ; +extern void ds1302ramWrite (const int addr, const unsigned int data) ; + +extern void ds1302clockRead (int clockData [8]) ; +extern void ds1302clockWrite (const int clockData [8]) ; + +extern void ds1302trickleCharge (const int diodes, const int resistors) ; + +extern void ds1302setup (const int clockPin, const int dataPin, const int csPin) ; + +#ifdef __cplusplus +} +#endif diff --git a/devLib/gertboard.c b/devLib/gertboard.c new file mode 100644 index 0000000..6a84415 --- /dev/null +++ b/devLib/gertboard.c @@ -0,0 +1,164 @@ +/* + * gertboard.c: + * Access routines for the SPI devices on the Gertboard + * Copyright (c) 2012 Gordon Henderson + * + * The Gertboard has: + * + * An MCP3002 dual-channel A to D convertor connected + * to the SPI bus, selected by chip-select A, and: + * + * An MCP4802 dual-channel D to A convertor connected + * to the SPI bus, selected via chip-select B. + * + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + + +#include +#include +#include +#include +#include + +#include +#include + +#include "gertboard.h" + +// The A-D convertor won't run at more than 1MHz @ 3.3v + +#define SPI_ADC_SPEED 1000000 +#define SPI_DAC_SPEED 1000000 +#define SPI_A2D 0 +#define SPI_D2A 1 + + +/* + * gertboardAnalogWrite: + * Write an 8-bit data value to the MCP4802 Analog to digital + * convertor on the Gertboard. + ********************************************************************************* + */ + +void gertboardAnalogWrite (const int chan, const int value) +{ + uint8_t spiData [2] ; + uint8_t chanBits, dataBits ; + + if (chan == 0) + chanBits = 0x30 ; + else + chanBits = 0xB0 ; + + chanBits |= ((value >> 4) & 0x0F) ; + dataBits = ((value << 4) & 0xF0) ; + + spiData [0] = chanBits ; + spiData [1] = dataBits ; + + wiringPiSPIDataRW (SPI_D2A, spiData, 2) ; +} + + +/* + * gertboardAnalogRead: + * Return the analog value of the given channel (0/1). + * The A/D is a 10-bit device + ********************************************************************************* + */ + +int gertboardAnalogRead (const int chan) +{ + uint8_t spiData [2] ; + + uint8_t chanBits ; + + if (chan == 0) + chanBits = 0b11010000 ; + else + chanBits = 0b11110000 ; + + spiData [0] = chanBits ; + spiData [1] = 0 ; + + wiringPiSPIDataRW (SPI_A2D, spiData, 2) ; + + return ((spiData [0] << 8) | (spiData [1] >> 1)) & 0x3FF ; +} + + +/* + * gertboardSPISetup: + * Initialise the SPI bus, etc. + ********************************************************************************* + */ + +int gertboardSPISetup (void) +{ + if (wiringPiSPISetup (SPI_A2D, SPI_ADC_SPEED) < 0) + return -1 ; + + if (wiringPiSPISetup (SPI_D2A, SPI_DAC_SPEED) < 0) + return -1 ; + + return 0 ; +} + + +/* + * New wiringPi node extension methods. + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, const int chan) +{ + return gertboardAnalogRead (chan - node->pinBase) ; +} + +static void myAnalogWrite (struct wiringPiNodeStruct *node, const int chan, const int value) +{ + gertboardAnalogWrite (chan - node->pinBase, value) ; +} + + +/* + * gertboardAnalogSetup: + * Create a new wiringPi device node for the analog devices on the + * Gertboard. We create one node with 2 pins - each pin being read + * and write - although the operations actually go to different + * hardware devices. + ********************************************************************************* + */ + +int gertboardAnalogSetup (const int pinBase) +{ + struct wiringPiNodeStruct *node ; + int x ; + + if (( x = gertboardSPISetup ()) != 0) + return x; + + node = wiringPiNewNode (pinBase, 2) ; + node->analogRead = myAnalogRead ; + node->analogWrite = myAnalogWrite ; + + return 0 ; +} diff --git a/devLib/gertboard.h b/devLib/gertboard.h new file mode 100644 index 0000000..3fa1919 --- /dev/null +++ b/devLib/gertboard.h @@ -0,0 +1,45 @@ +/* + * gertboard.h: + * Access routines for the SPI devices on the Gertboard + * Copyright (c) 2012 Gordon Henderson + * + * The Gertboard has an MCP4802 dual-channel D to A convertor + * connected to the SPI bus, selected via chip-select B. + * + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +// Old routines + +extern void gertboardAnalogWrite (const int chan, const int value) ; +extern int gertboardAnalogRead (const int chan) ; +extern int gertboardSPISetup (void) ; + +// New + +extern int gertboardAnalogSetup (const int pinBase) ; + +#ifdef __cplusplus +} +#endif diff --git a/devLib/maxdetect.c b/devLib/maxdetect.c new file mode 100644 index 0000000..74ff70e --- /dev/null +++ b/devLib/maxdetect.c @@ -0,0 +1,238 @@ +/* + * maxdetect.c: + * Driver for the MaxDetect series sensors + * + * Copyright (c) 2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +//#include +//#include + +#include + +#include "maxdetect.h" + +#ifndef TRUE +# define TRUE (1==1) +# define FALSE (1==2) +#endif + + +/* + * maxDetectLowHighWait: + * Wait for a transition from low to high on the bus + ********************************************************************************* + */ + +static int maxDetectLowHighWait (const int pin) +{ + struct timeval now, timeOut, timeUp ; + +// If already high then wait for pin to go low + + gettimeofday (&now, NULL) ; + timerclear (&timeOut) ; + timeOut.tv_usec = 1000 ; + timeradd (&now, &timeOut, &timeUp) ; + + while (digitalRead (pin) == HIGH) + { + gettimeofday (&now, NULL) ; + if (timercmp (&now, &timeUp, >)) + return FALSE ; + } + +// Wait for it to go HIGH + + gettimeofday (&now, NULL) ; + timerclear (&timeOut) ; + timeOut.tv_usec = 1000 ; + timeradd (&now, &timeOut, &timeUp) ; + + while (digitalRead (pin) == LOW) + { + gettimeofday (&now, NULL) ; + if (timercmp (&now, &timeUp, >)) + return FALSE ; + } + + return TRUE ; +} + + +/* + * maxDetectClockByte: + * Read in a single byte from the MaxDetect bus + ********************************************************************************* + */ + +static unsigned int maxDetectClockByte (const int pin) +{ + unsigned int byte = 0 ; + int bit ; + + for (bit = 0 ; bit < 8 ; ++bit) + { + if (!maxDetectLowHighWait (pin)) + return 0 ; + +// bit starting now - we need to time it. + + delayMicroseconds (30) ; + byte <<= 1 ; + if (digitalRead (pin) == HIGH) // It's a 1 + byte |= 1 ; + } + + return byte ; +} + + +/* + * maxDetectRead: + * Read in and return the 4 data bytes from the MaxDetect sensor. + * Return TRUE/FALSE depending on the checksum validity + ********************************************************************************* + */ + +int maxDetectRead (const int pin, unsigned char buffer [4]) +{ + int i ; + unsigned int checksum ; + unsigned char localBuf [5] ; + struct timeval now, then, took ; + +// See how long we took + + gettimeofday (&then, NULL) ; + +// Wake up the RHT03 by pulling the data line low, then high +// Low for 10mS, high for 40uS. + + pinMode (pin, OUTPUT) ; + digitalWrite (pin, 0) ; delay (10) ; + digitalWrite (pin, 1) ; delayMicroseconds (40) ; + pinMode (pin, INPUT) ; + +// Now wait for sensor to pull pin low + + if (!maxDetectLowHighWait (pin)) + return FALSE ; + +// and read in 5 bytes (40 bits) + + for (i = 0 ; i < 5 ; ++i) + localBuf [i] = maxDetectClockByte (pin) ; + + checksum = 0 ; + for (i = 0 ; i < 4 ; ++i) + { + buffer [i] = localBuf [i] ; + checksum += localBuf [i] ; + } + checksum &= 0xFF ; + +// See how long we took + + gettimeofday (&now, NULL) ; + timersub (&now, &then, &took) ; + +// Total time to do this should be: +// 10mS + 40µS - reset +// + 80µS + 80µS - sensor doing its low -> high thing +// + 40 * (50µS + 27µS (0) or 70µS (1) ) +// = 15010µS +// so if we take more than that, we've had a scheduling interruption and the +// reading is probably bogus. + + if ((took.tv_sec != 0) || (took.tv_usec > 16000)) + return FALSE ; + + return checksum == localBuf [4] ; +} + + +/* + * readRHT03: + * Read the Temperature & Humidity from an RHT03 sensor + * Values returned are *10, so 123 is 12.3. + ********************************************************************************* + */ + +int readRHT03 (const int pin, int *temp, int *rh) +{ + static struct timeval then ; // will initialise to zero + static int lastTemp = 0 ; + static int lastRh = 0 ; + + int result ; + struct timeval now, timeOut ; + unsigned char buffer [4] ; + +// The data sheets say to not read more than once every 2 seconds, so you +// get the last good reading + + gettimeofday (&now, NULL) ; + if (timercmp (&now, &then, <)) + { + *rh = lastRh ; + *temp = lastTemp ; + return TRUE ; + } + +// Set timeout for next read + + gettimeofday (&now, NULL) ; + timerclear (&timeOut) ; + timeOut.tv_sec = 2 ; + timeradd (&now, &timeOut, &then) ; + +// Read ... + + result = maxDetectRead (pin, buffer) ; + + if (!result) // Try again, but just once + result = maxDetectRead (pin, buffer) ; + + if (!result) + return FALSE ; + + *rh = (buffer [0] * 256 + buffer [1]) ; + *temp = (buffer [2] * 256 + buffer [3]) ; + + if ((*temp & 0x8000) != 0) // Negative + { + *temp &= 0x7FFF ; + *temp = -*temp ; + } + +// Discard obviously bogus readings - the checksum can't detect a 2-bit error +// (which does seem to happen - no realtime here) + + if ((*rh > 999) || (*temp > 800) || (*temp < -400)) + return FALSE ; + + lastRh = *rh ; + lastTemp = *temp ; + + return TRUE ; +} diff --git a/devLib/maxdetect.h b/devLib/maxdetect.h new file mode 100644 index 0000000..a1fd742 --- /dev/null +++ b/devLib/maxdetect.h @@ -0,0 +1,40 @@ +/* + * maxdetect.h: + * Driver for the MaxDetect series sensors + * + * Copyright (c) 2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + + +#ifdef __cplusplus +extern "C" { +#endif + +// Main generic function + +int maxDetectRead (const int pin, unsigned char buffer [4]) ; + +// Individual sensors + +int readRHT03 (const int pin, int *temp, int *rh) ; + +#ifdef __cplusplus +} +#endif diff --git a/devLib/piFace.c b/devLib/piFace.c new file mode 100644 index 0000000..4475c7f --- /dev/null +++ b/devLib/piFace.c @@ -0,0 +1,112 @@ +/* + * piFace.: + * This file to interface with the PiFace peripheral device which + * has an MCP23S17 GPIO device connected via the SPI bus. + * + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + + +#include +#include + +#include +#include + +#include "piFace.h" + + +/* + * myDigitalWrite: + * Perform the digitalWrite function on the PiFace board + ********************************************************************************* + */ + +void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + digitalWrite (pin + 16, value) ; +} + + +/* + * myDigitalRead: + * Perform the digitalRead function on the PiFace board + * With a slight twist - if we read from base + 8, then we + * read from the output latch... + ********************************************************************************* + */ + +int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + if ((pin - node->pinBase) >= 8) + return digitalRead (pin + 8) ; + else + return digitalRead (pin + 16 + 8) ; +} + + +/* + * myPullUpDnControl: + * Perform the pullUpDnControl function on the PiFace board + ********************************************************************************* + */ + +void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int pud) +{ + pullUpDnControl (pin + 16 + 8, pud) ; +} + + +/* + * piFaceSetup + * We're going to create an instance of the mcp23s17 here, then + * provide our own read/write routines on-top of it... + * The supplied PiFace code (in Pithon) treats it as an 8-bit device + * where you write the output ports and read the input port using the + * same pin numbers, however I have had a request to be able to read + * the output port, so reading 8..15 will read the output latch. + ********************************************************************************* + */ + +int piFaceSetup (const int pinBase) +{ + int i ; + struct wiringPiNodeStruct *node ; + +// Create an mcp23s17 instance: + + mcp23s17Setup (pinBase + 16, 0, 0) ; + +// Set the direction bits + + for (i = 0 ; i < 8 ; ++i) + { + pinMode (pinBase + 16 + i, OUTPUT) ; // Port A is the outputs + pinMode (pinBase + 16 + 8 + i, INPUT) ; // Port B inputs. + } + + node = wiringPiNewNode (pinBase, 16) ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; + node->pullUpDnControl = myPullUpDnControl ; + + return 0 ; +} diff --git a/devLib/piFace.h b/devLib/piFace.h new file mode 100644 index 0000000..4965314 --- /dev/null +++ b/devLib/piFace.h @@ -0,0 +1,32 @@ +/* + * piFace.h: + * Control the PiFace Interface board for the Raspberry Pi + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int piFaceSetup (const int pinBase) ; + +#ifdef __cplusplus +} +#endif diff --git a/devLib/piFaceOld.c b/devLib/piFaceOld.c new file mode 100644 index 0000000..cadbfe8 --- /dev/null +++ b/devLib/piFaceOld.c @@ -0,0 +1,177 @@ +/* + * piFace.: + * Copyright (c) 2012-2016 Gordon Henderson + * + * This file to interface with the PiFace peripheral device which + * has an MCP23S17 GPIO device connected via the SPI bus. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + + +#include +#include + +#include +#include + +#include "../wiringPi/mcp23x0817.h" + +#include "piFace.h" + +#define PIFACE_SPEED 4000000 +#define PIFACE_DEVNO 0 + + + +/* + * writeByte: + * Write a byte to a register on the MCP23S17 on the SPI bus. + ********************************************************************************* + */ + +static void writeByte (uint8_t reg, uint8_t data) +{ + uint8_t spiData [4] ; + + spiData [0] = CMD_WRITE ; + spiData [1] = reg ; + spiData [2] = data ; + + wiringPiSPIDataRW (PIFACE_DEVNO, spiData, 3) ; +} + +/* + * readByte: + * Read a byte from a register on the MCP23S17 on the SPI bus. + ********************************************************************************* + */ + +static uint8_t readByte (uint8_t reg) +{ + uint8_t spiData [4] ; + + spiData [0] = CMD_READ ; + spiData [1] = reg ; + + wiringPiSPIDataRW (PIFACE_DEVNO, spiData, 3) ; + + return spiData [2] ; +} + + +/* + * myDigitalWrite: + * Perform the digitalWrite function on the PiFace board + ********************************************************************************* + */ + +void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + uint8_t mask, old ; + + pin -= node->pinBase ; + mask = 1 << pin ; + old = readByte (MCP23x17_GPIOA) ; + + if (value == 0) + old &= (~mask) ; + else + old |= mask ; + + writeByte (MCP23x17_GPIOA, old) ; +} + + +/* + * myDigitalRead: + * Perform the digitalRead function on the PiFace board + ********************************************************************************* + */ + +int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + uint8_t mask, reg ; + + mask = 1 << ((pin - node->pinBase) & 7) ; + + if (pin < 8) + reg = MCP23x17_GPIOB ; // Input regsiter + else + reg = MCP23x17_OLATA ; // Output latch regsiter + + if ((readByte (reg) & mask) != 0) + return HIGH ; + else + return LOW ; +} + + +/* + * myPullUpDnControl: + * Perform the pullUpDnControl function on the PiFace board + ********************************************************************************* + */ + +void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int pud) +{ + uint8_t mask, old ; + + mask = 1 << (pin - node->pinBase) ; + old = readByte (MCP23x17_GPPUB) ; + + if (pud == 0) + old &= (~mask) ; + else + old |= mask ; + + writeByte (MCP23x17_GPPUB, old) ; +} + + +/* + * piFaceSetup + * Setup the SPI interface and initialise the MCP23S17 chip + * We create one node with 16 pins - each if the first 8 pins being read + * and write - although the operations actually go to different + * hardware ports. The top 8 let you read the state of the output register. + ********************************************************************************* + */ + +int piFaceSetup (const int pinBase) +{ + int x ; + struct wiringPiNodeStruct *node ; + + if ((x = wiringPiSPISetup (PIFACE_DEVNO, PIFACE_SPEED)) < 0) + return x ; + +// Setup the MCP23S17 + + writeByte (MCP23x17_IOCON, IOCON_INIT) ; + writeByte (MCP23x17_IODIRA, 0x00) ; // Port A -> Outputs + writeByte (MCP23x17_IODIRB, 0xFF) ; // Port B -> Inputs + + node = wiringPiNewNode (pinBase, 16) ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; + node->pullUpDnControl = myPullUpDnControl ; + + return 0 ; +} diff --git a/devLib/piGlow.c b/devLib/piGlow.c new file mode 100644 index 0000000..44e3db8 --- /dev/null +++ b/devLib/piGlow.c @@ -0,0 +1,118 @@ +/* + * piGlow.c: + * Easy access to the Pimoroni PiGlow board. + * + * Copyright (c) 2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include + +#include "piGlow.h" + +#define PIGLOW_BASE 577 + +static int leg0 [6] = { 6, 7, 8, 5, 4, 9 } ; +static int leg1 [6] = { 17, 16, 15, 13, 11, 10 } ; +static int leg2 [6] = { 0, 1, 2, 3, 14, 12 } ; + + +/* + * piGlow1: + * Light up an individual LED + ********************************************************************************* + */ + +void piGlow1 (const int leg, const int ring, const int intensity) +{ + int *legLeds ; + + if ((leg < 0) || (leg > 2)) return ; + if ((ring < 0) || (ring > 5)) return ; + + /**/ if (leg == 0) + legLeds = leg0 ; + else if (leg == 1) + legLeds = leg1 ; + else + legLeds = leg2 ; + + analogWrite (PIGLOW_BASE + legLeds [ring], intensity) ; +} + +/* + * piGlowLeg: + * Light up all 6 LEDs on a leg + ********************************************************************************* + */ + +void piGlowLeg (const int leg, const int intensity) +{ + int i ; + int *legLeds ; + + if ((leg < 0) || (leg > 2)) + return ; + + /**/ if (leg == 0) + legLeds = leg0 ; + else if (leg == 1) + legLeds = leg1 ; + else + legLeds = leg2 ; + + for (i = 0 ; i < 6 ; ++i) + analogWrite (PIGLOW_BASE + legLeds [i], intensity) ; +} + + +/* + * piGlowRing: + * Light up 3 LEDs in a ring. Ring 0 is the outermost, 5 the innermost + ********************************************************************************* + */ + +void piGlowRing (const int ring, const int intensity) +{ + if ((ring < 0) || (ring > 5)) + return ; + + analogWrite (PIGLOW_BASE + leg0 [ring], intensity) ; + analogWrite (PIGLOW_BASE + leg1 [ring], intensity) ; + analogWrite (PIGLOW_BASE + leg2 [ring], intensity) ; +} + +/* + * piGlowSetup: + * Initialise the board & remember the pins we're using + ********************************************************************************* + */ + +void piGlowSetup (int clear) +{ + sn3218Setup (PIGLOW_BASE) ; + + if (clear) + { + piGlowLeg (0, 0) ; + piGlowLeg (1, 0) ; + piGlowLeg (2, 0) ; + } +} diff --git a/devLib/piGlow.h b/devLib/piGlow.h new file mode 100644 index 0000000..a4d89d0 --- /dev/null +++ b/devLib/piGlow.h @@ -0,0 +1,45 @@ +/* + * piglow.h: + * Easy access to the Pimoroni PiGlow board. + * + * Copyright (c) 2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + + +#define PIGLOW_RED 0 +#define PIGLOW_ORANGE 1 +#define PIGLOW_YELLOW 2 +#define PIGLOW_GREEN 3 +#define PIGLOW_BLUE 4 +#define PIGLOW_WHITE 5 + + +#ifdef __cplusplus +extern "C" { +#endif + +extern void piGlow1 (const int leg, const int ring, const int intensity) ; +extern void piGlowLeg (const int leg, const int intensity) ; +extern void piGlowRing (const int ring, const int intensity) ; +extern void piGlowSetup (int clear) ; + +#ifdef __cplusplus +} +#endif diff --git a/devLib/piNes.c b/devLib/piNes.c new file mode 100644 index 0000000..a115050 --- /dev/null +++ b/devLib/piNes.c @@ -0,0 +1,113 @@ +/* + * piNes.c: + * Driver for the NES Joystick controller on the Raspberry Pi + * Copyright (c) 2012 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include + +#include "piNes.h" + +#define MAX_NES_JOYSTICKS 8 + +#define NES_RIGHT 0x01 +#define NES_LEFT 0x02 +#define NES_DOWN 0x04 +#define NES_UP 0x08 +#define NES_START 0x10 +#define NES_SELECT 0x20 +#define NES_B 0x40 +#define NES_A 0x80 + + +#define PULSE_TIME 25 + +// Data to store the pins for each controller + +struct nesPinsStruct +{ + unsigned int cPin, dPin, lPin ; +} ; + +static struct nesPinsStruct nesPins [MAX_NES_JOYSTICKS] ; + +static int joysticks = 0 ; + + +/* + * setupNesJoystick: + * Create a new NES joystick interface, program the pins, etc. + ********************************************************************************* + */ + +int setupNesJoystick (int dPin, int cPin, int lPin) +{ + if (joysticks == MAX_NES_JOYSTICKS) + return -1 ; + + nesPins [joysticks].dPin = dPin ; + nesPins [joysticks].cPin = cPin ; + nesPins [joysticks].lPin = lPin ; + + digitalWrite (lPin, LOW) ; + digitalWrite (cPin, LOW) ; + + pinMode (lPin, OUTPUT) ; + pinMode (cPin, OUTPUT) ; + pinMode (dPin, INPUT) ; + + return joysticks++ ; +} + + +/* + * readNesJoystick: + * Do a single scan of the NES Joystick. + ********************************************************************************* + */ + +unsigned int readNesJoystick (int joystick) +{ + unsigned int value = 0 ; + int i ; + + struct nesPinsStruct *pins = &nesPins [joystick] ; + +// Toggle Latch - which presents the first bit + + digitalWrite (pins->lPin, HIGH) ; delayMicroseconds (PULSE_TIME) ; + digitalWrite (pins->lPin, LOW) ; delayMicroseconds (PULSE_TIME) ; + +// Read first bit + + value = digitalRead (pins->dPin) ; + +// Now get the next 7 bits with the clock + + for (i = 0 ; i < 7 ; ++i) + { + digitalWrite (pins->cPin, HIGH) ; delayMicroseconds (PULSE_TIME) ; + digitalWrite (pins->cPin, LOW) ; delayMicroseconds (PULSE_TIME) ; + value = (value << 1) | digitalRead (pins->dPin) ; + } + + return value ^ 0xFF ; +} diff --git a/devLib/piNes.h b/devLib/piNes.h new file mode 100644 index 0000000..897f181 --- /dev/null +++ b/devLib/piNes.h @@ -0,0 +1,45 @@ +/* + * piNes.h: + * Driver for the NES Joystick controller on the Raspberry Pi + * Copyright (c) 2012 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#define MAX_NES_JOYSTICKS 8 + +#define NES_RIGHT 0x01 +#define NES_LEFT 0x02 +#define NES_DOWN 0x04 +#define NES_UP 0x08 +#define NES_START 0x10 +#define NES_SELECT 0x20 +#define NES_B 0x40 +#define NES_A 0x80 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int setupNesJoystick (int dPin, int cPin, int lPin) ; +extern unsigned int readNesJoystick (int joystick) ; + +#ifdef __cplusplus +} +#endif diff --git a/devLib/scrollPhat.c b/devLib/scrollPhat.c new file mode 100644 index 0000000..c1a6f11 --- /dev/null +++ b/devLib/scrollPhat.c @@ -0,0 +1,430 @@ +/* + * scrollPhat.c: + * Simple driver for the Pimoroni Scroll Phat device + * + * Copyright (c) 2015 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include + +#include + +#include "scrollPhatFont.h" +#include "scrollPhat.h" + +// Size + +#define SP_WIDTH 11 +#define SP_HEIGHT 5 + +// I2C + +#define PHAT_I2C_ADDR 0x60 + +// Software copy of the framebuffer +// it's 8-bit deep although the display itself is only 1-bit deep. + +static unsigned char frameBuffer [SP_WIDTH * SP_HEIGHT] ; + +static int lastX, lastY ; +static int printDelayFactor ; +static int scrollPhatFd ; + +static int putcharX ; + +#undef DEBUG + + +/* + * delay: + * Wait for some number of milliseconds. + * This taken from wiringPi as there is no-need to include the whole of + * wiringPi just for the delay function. + ********************************************************************************* + */ + +static void delay (unsigned int howLong) +{ + struct timespec sleeper, dummy ; + + sleeper.tv_sec = (time_t)(howLong / 1000) ; + sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ; + + nanosleep (&sleeper, &dummy) ; +} + + + +/* + * scrollPhatUpdate: + * Copy our software version to the real display + ********************************************************************************* + */ + +void scrollPhatUpdate (void) +{ + register int x, y ; + register unsigned char data, pixel ; + unsigned char pixels [SP_WIDTH] ; + +#ifdef DEBUG + printf ("+-----------+\n") ; + for (y = 0 ; y < SP_HEIGHT ; ++y) + { + putchar ('|') ; + for (x = 0 ; x < SP_WIDTH ; ++x) + { + pixel = frameBuffer [x + y * SP_WIDTH] ; + putchar (pixel == 0 ? ' ' : '*') ; + } + printf ("|\n") ; + } + printf ("+-----------+\n") ; +#endif + + for (x = 0 ; x < SP_WIDTH ; ++x) + { + data = 0 ; + for (y = 0 ; y < SP_HEIGHT ; ++y) + { + pixel = frameBuffer [x + y * SP_WIDTH] ; + data = (data << 1) | ((pixel == 0) ? 0 : 1) ; + } + pixels [x] = data ; + } + + for (x = 0 ; x < SP_WIDTH ; ++x) + wiringPiI2CWriteReg8 (scrollPhatFd, 1 + x, pixels [x]) ; + + wiringPiI2CWriteReg8 (scrollPhatFd, 0x0C, 0) ; +} + + +/* + ********************************************************************************* + * Standard Graphical Functions + ********************************************************************************* + */ + + +/* + * scrollPhatPoint: + * Plot a pixel. Crude clipping - speed is not the essence here. + ********************************************************************************* + */ + +void scrollPhatPoint (int x, int y, int colour) +{ + lastX = x ; + lastY = y ; + + if ((x < 0) || (x >= SP_WIDTH) || (y < 0) || (y >= SP_HEIGHT)) + return ; + + frameBuffer [x + y * SP_WIDTH] = colour ; +} + + +/* + * scrollPhatLine: scrollPhatLineTo: + * Classic Bressenham Line code - rely on the point function to do the + * clipping for us here. + ********************************************************************************* + */ + +void scrollPhatLine (int x0, int y0, int x1, int y1, int colour) +{ + int dx, dy ; + int sx, sy ; + int err, e2 ; + + lastX = x1 ; + lastY = y1 ; + + dx = abs (x1 - x0) ; + dy = abs (y1 - y0) ; + + sx = (x0 < x1) ? 1 : -1 ; + sy = (y0 < y1) ? 1 : -1 ; + + err = dx - dy ; + + for (;;) + { + scrollPhatPoint (x0, y0, colour) ; + + if ((x0 == x1) && (y0 == y1)) + break ; + + e2 = 2 * err ; + + if (e2 > -dy) + { + err -= dy ; + x0 += sx ; + } + + if (e2 < dx) + { + err += dx ; + y0 += sy ; + } + } + +} + +void scrollPhatLineTo (int x, int y, int colour) +{ + scrollPhatLine (lastX, lastY, x, y, colour) ; +} + + +/* + * scrollPhatRectangle: + * A rectangle is a spoilt days fishing + ********************************************************************************* + */ + +void scrollPhatRectangle (int x1, int y1, int x2, int y2, int colour, int filled) +{ + register int x ; + + if (filled) + { + /**/ if (x1 == x2) + scrollPhatLine (x1, y1, x2, y2, colour) ; + else if (x1 < x2) + for (x = x1 ; x <= x2 ; ++x) + scrollPhatLine (x, y1, x, y2, colour) ; + else + for (x = x2 ; x <= x1 ; ++x) + scrollPhatLine (x, y1, x, y2, colour) ; + } + else + { + scrollPhatLine (x1, y1, x2, y1, colour) ; + scrollPhatLineTo (x2, y2, colour) ; + scrollPhatLineTo (x1, y2, colour) ; + scrollPhatLineTo (x1, y1, colour) ; + } +} + + +/* + * scrollPhatPutchar: + * Print a single character to the screen then advance the pointer by an + * appropriate ammount (variable width font). + * We rely on the clipping done by the pixel plot function to keep us + * out of trouble. + * Return the width + space + ********************************************************************************* + */ + +int scrollPhatPutchar (int c) +{ + register int x, y ; + + unsigned char line ; + unsigned char *fontPtr ; + unsigned char *p2 ; + int lineWidth, width, mask ; + +// The font is printable characters, uppercase only... +// and somewhat varaible width... + + c &= 0x7F ; + if (c > 0x60) + c -= 64 ; + else + c -= 32 ; + + fontPtr = scrollPhatFont + c * fontHeight ; + +// Work out width of this character +// There probably is a more efficient way to do this, but... + + p2 = fontPtr ; + width = 0 ; + for (y = 0 ; y < fontHeight ; ++y) + { + mask = 0x80 ; + for (lineWidth = 8 ; lineWidth > 0 ; --lineWidth) + { + if ((*p2 & mask) != 0) + break ; + mask >>= 1 ; + } + if (lineWidth > width) + width = lineWidth ; + + ++p2 ; + } + + if (width == 0) // Likely to be a blank or space character + width = 3 ; + + for (y = fontHeight - 1 ; y >= 0 ; --y) + { + x = 0 ; + line = *fontPtr++ ; + for (mask = 1 << (width - 1) ; mask != 0 ; mask >>= 1) + { + scrollPhatPoint (putcharX + x, y, (line & mask)) ; + ++x ; + } + } + +// make a line of space + + for (y = fontHeight - 1 ; y >= 0 ; --y) + scrollPhatPoint (putcharX + width, y, 0) ; + + putcharX = putcharX + width + 1 ; + + return width + 1 ; +} + + +/* + * scrollPhatPuts: + * Send a string to the display - and scroll it across. + * This is somewhat of a hack in that we print the entire string to the + * display and let the point clipping take care of what's off-screen... + ********************************************************************************* + */ + +void scrollPhatPuts (const char *str) +{ + int i ; + int movingX = 0 ; + const char *s ; + int pixelLen ; + +// Print it once, then we know the width in pixels... + + putcharX = 0 ; + s = str ; + while (*s) + scrollPhatPutchar (*s++) ; + + pixelLen = putcharX ; + +// Now scroll it by printing it and moving left one pixel + + movingX = 0 ; + for (i = 0 ; i < pixelLen ; ++i) + { + putcharX = movingX ; + s = str ; + while (*s) + scrollPhatPutchar (*s++) ; + --movingX ; + scrollPhatUpdate () ; + delay (printDelayFactor) ; + } +} + + +/* + * scrollPhatPrintf: + * Does what it says + ********************************************************************************* + */ + +void scrollPhatPrintf (const char *message, ...) +{ + va_list argp ; + char buffer [1024] ; + + va_start (argp, message) ; + vsnprintf (buffer, 1023, message, argp) ; + va_end (argp) ; + + scrollPhatPuts (buffer) ; +} + + +/* + * scrollPhatPrintSpeed: + * Change the print speed - mS per shift by 1 pixel + ********************************************************************************* + */ + +void scrollPhatPrintSpeed (const int pps) +{ + if (pps < 0) + printDelayFactor = 0 ; + else + printDelayFactor = pps ; +} + + +/* + * scrollPhatClear: + * Clear the display + ********************************************************************************* + */ + +void scrollPhatClear (void) +{ + register int i ; + register unsigned char *ptr = frameBuffer ; + + for (i = 0 ; i < (SP_WIDTH * SP_HEIGHT) ; ++i) + *ptr++ = 0 ; + + scrollPhatUpdate () ; +} + + +/* + * scrollPhatIntensity: + * Set the display brightness - percentage + ********************************************************************************* + */ + +void scrollPhatIntensity (const int percent) +{ + wiringPiI2CWriteReg8 (scrollPhatFd, 0x19, (127 * percent) / 100) ; +} + + +/* + * scrollPhatSetup: + * Initialise the Scroll Phat display + ********************************************************************************* + */ + +int scrollPhatSetup (void) +{ + if ((scrollPhatFd = wiringPiI2CSetup (PHAT_I2C_ADDR)) < 0) + return scrollPhatFd ; + + wiringPiI2CWriteReg8 (scrollPhatFd, 0x00, 0x03) ; // Enable display, set to 5x11 mode + scrollPhatIntensity (10) ; + scrollPhatClear () ; + scrollPhatPrintSpeed (100) ; + + return 0 ; +} diff --git a/devLib/scrollPhat.h b/devLib/scrollPhat.h new file mode 100644 index 0000000..0e762b1 --- /dev/null +++ b/devLib/scrollPhat.h @@ -0,0 +1,39 @@ +/* + * scrollPhat.h: + * Simple driver for the Pimoroni Scroll Phat device + * + * Copyright (c) 2015 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +extern void scrollPhatPoint (int x, int y, int colour) ; +extern void scrollPhatLine (int x0, int y0, int x1, int y1, int colour) ; +extern void scrollPhatLineTo (int x, int y, int colour) ; +extern void scrollPhatRectangle (int x1, int y1, int x2, int y2, int colour, int filled) ; +extern void scrollPhatUpdate (void) ; +extern void scrollPhatClear (void) ; + +extern int scrollPhatPutchar (int c) ; +//extern void scrollPhatPutchar (int c) ; +extern void scrollPhatPuts (const char *str) ; +extern void scrollPhatPrintf (const char *message, ...) ; +extern void scrollPhatPrintSpeed (const int cps10) ; + +extern void scrollPhatIntensity (const int percent) ; +extern int scrollPhatSetup (void) ; diff --git a/devLib/scrollPhatFont.h b/devLib/scrollPhatFont.h new file mode 100644 index 0000000..92f623a --- /dev/null +++ b/devLib/scrollPhatFont.h @@ -0,0 +1,544 @@ +/* + * scrollPhatFont.h: + * Simple font for the Pimoroni Scroll Phat. + * Note: this is a very much reduced font - 5 pixels high and + * mostly 4 pixels wide - sometimes 5. Also only + * printable characters from space to _ uppercase only. + * + * Copyright (c) 2015-2016 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +static const int fontHeight = 5 ; + +static unsigned char scrollPhatFont [] = +{ + +// 0x20, Space. Handeled as a special case in the code. + + 0x0, // .... + 0x0, // .... + 0x0, // .... + 0x0, // .... + 0x0, // .... + +// 0x21, ! + + 0x1, // * + 0x1, // * + 0x1, // * + 0x0, // . + 0x1, // * + +// 0x22, " + + 0x5, // *..* + 0x5, // *..* + 0x0, // .... + 0x0, // .... + 0x0, // .... + +// 0x23, # + + 0x9, // *..* + 0xF, // **** + 0x9, // *..* + 0xF, // **** + 0x9, // *..* + +// 0x24, $ + + 0x1, // ..*. + 0x7, // .*** + 0x2, // ..*. + 0xE, // ***. + 0x8, // ..*. + +// 0x25, % + + 0x9, // *..* + 0x1, // ...* + 0x6, // .**. + 0x8, // *... + 0x9, // *..* + +// 0x26, & + + 0x6, // .**. + 0x8, // *... + 0x4, // .*.. + 0xA, // *.*. + 0x5, // .*.* + +// 0x27, ' + + 0x1, // .* + 0x2, // *. + 0x0, // .. + 0x0, // .. + 0x0, // .. + +// 0x28, ( + + 0x3, // ..** + 0x4, // .*.. + 0x8, // *... + 0x4, // .*.. + 0x3, // ..** + +// 0x29, ) + + 0xC, // **.. + 0x2, // ..*. + 0x1, // ...* + 0x2, // ..*. + 0xC, // **.. + +// 0x2A, * + + 0x9, // *..* + 0x6, // .**. + 0xF, // **** + 0x6, // .**. + 0x9, // *..* + +// 0x2B, + + + 0x6, // .**. + 0x6, // .**. + 0xF, // **** + 0x6, // .**. + 0x6, // .**. + +// 0x2C, , + + 0x0, // .. + 0x0, // .. + 0x0, // .. + 0x1, // .* + 0x2, // *. + +// 0x2D, - + + 0x0, // .... + 0x0, // .... + 0xF, // **** + 0x0, // .... + 0x0, // .... + +// 0x2E, . + + 0x0, // . + 0x0, // . + 0x0, // . + 0x0, // . + 0x1, // * + +// 0x2F, / + + 0x1, // ...* + 0x3, // ..** + 0x4, // ..*. + 0xC, // **.. + 0x8, // *... + +// 0x30, 0 + + 0x6, // .**. + 0x9, // *..* + 0x9, // *..* + 0x9, // *..* + 0x6, // .**. + +// 0x31, 1 + + 0x2, // ..*. + 0x6, // .**. + 0x2, // ..*. + 0x2, // ..*. + 0x7, // .*** + +// 0x32, 2 + + 0x6, // .**. + 0x1, // ...* + 0x6, // .**. + 0x8, // *... + 0xF, // **** + +// 0x33, 3 + + 0xE, // ***. + 0x1, // ...* + 0xE, // ***. + 0x1, // ...* + 0xE, // ***. + +// 0x34, 4 + + 0x6, // .**. + 0xA, // *.*. + 0xF, // **** + 0x2, // ..*. + 0x2, // ..*. + +// 0x35, 5 + + 0xF, // **** + 0x8, // *... + 0xF, // **** + 0x1, // ...* + 0xE, // ***. + +// 0x36, 6 + + 0x2, // ..*. + 0x4, // .*.. + 0xA, // *.*. + 0x9, // *..* + 0x6, // .**. + +// 0x37, 7 + + 0xF, // **** + 0x1, // ...* + 0x2, // ..*. + 0x4, // .*.. + 0x8, // *... + +// 0x38, 8 + + 0x6, // .**. + 0x9, // *..* + 0x6, // .**. + 0x9, // *..* + 0x6, // .**. + +// 0x39, 9 + + 0x6, // .**. + 0x9, // *..* + 0x7, // .*.* + 0x1, // ..*. + 0x2, // .*.. + +// 0x3A, : + + 0x0, // . + 0x1, // * + 0x0, // . + 0x1, // * + 0x0, // . + +// 0x3B, ; + + 0x0, // .. + 0x1, // .* + 0x0, // .. + 0x1, // .* + 0x2, // *. + +// 0x3C, < + + 0x2, // ..*. + 0x4, // .*.. + 0x8, // *... + 0x4, // .*.. + 0x2, // ..*. + +// 0x3D, = + + 0x0, // .... + 0xF, // **** + 0x0, // .... + 0xF, // **** + 0x0, // .... + +// 0x3E, > + + 0x0, // .*.. + 0x0, // ..*. + 0x0, // ...* + 0x0, // ..*. + 0x0, // .*.. + +// 0x3F, ? + + 0x6, // .**. + 0x1, // ...* + 0x2, // ..*. + 0x0, // .... + 0x2, // ..*. + +// 0x40, @ + + 0x6, // .**. + 0xD, // **.* + 0x8, // *... + 0x4, // .*.. + 0x3, // ..** + +// 0x41, A + + 0x6, // .**. + 0x9, // *..* + 0xF, // **** + 0x9, // *..* + 0x9, // *..* + +// 0x42, B + + 0xE, // ***. + 0x9, // *..* + 0xE, // ***. + 0x9, // *..* + 0xE, // ***. + +// 0x43, C + + 0x6, // .**. + 0x9, // *..* + 0x8, // *... + 0x9, // *..* + 0x6, // .**. + +// 0x44, D + + 0xE, // ***. + 0x9, // *..* + 0x9, // *..* + 0x9, // *..* + 0xE, // ***. + +// 0x45, E + + 0xF, // **** + 0x8, // *... + 0xE, // ***. + 0x8, // *... + 0xF, // **** + +// 0x46, F + + 0xF, // **** + 0x8, // *... + 0xE, // ***. + 0x8, // *... + 0x8, // *... + +// 0x47, G + + 0x6, // .**. + 0x9, // *..* + 0x8, // *... + 0xB, // *.** + 0x6, // .**. + +// 0x48, H + + 0x9, // *..* + 0x9, // *..* + 0xF, // **** + 0x9, // *..* + 0x9, // *..* + +// 0x49, I + + 0x7, // *** + 0x2, // .*. + 0x2, // .*. + 0x2, // .*. + 0x7, // *** + +// 0x4A, J + + 0x7, // .*** + 0x2, // ..*. + 0x2, // ..*. + 0xA, // *.*. + 0x4, // .*.. + +// 0x4B, K + + 0x9, // *..* + 0xA, // *.*. + 0xC, // **.. + 0xA, // *.*. + 0x9, // *..* + +// 0x4C, L + + 0x4, // *.. + 0x4, // *.. + 0x4, // *.. + 0x4, // *.. + 0x7, // *** + +// 0x4D, M + + 0x11, // *...* + 0x1B, // **.** + 0x15, // *.*.* + 0x11, // *...* + 0x11, // *...* + +// 0x4E, N + + 0x9, // *..* + 0xD, // **.* + 0xB, // *.** + 0x9, // *..* + 0x9, // *..* + +// 0x4F, O + + 0x6, // .**. + 0x9, // *..* + 0x9, // *..* + 0x9, // *..* + 0x6, // .**. + +// 0x50, P + + 0xE, // ***. + 0x9, // *..* + 0xE, // ***. + 0x8, // *... + 0x8, // *... + +// 0x51, Q + + 0x6, // .**. + 0x9, // *..* + 0x9, // *..* + 0xA, // *.*. + 0x5, // .*.* + +// 0x52, R + + 0xE, // ***. + 0x9, // *..* + 0xF, // ***. + 0xA, // *.*. + 0x9, // *..* + +// 0x53, S + + 0x6, // .**. + 0x8, // *... + 0x6, // .**. + 0x1, // ...* + 0x6, // .**. + +// 0x54, T + + 0x7, // .*** + 0x2, // ..*. + 0x2, // ..*. + 0x2, // ..*. + 0x2, // ..*. + +// 0x55, U + + 0x9, // *..* + 0x9, // *..* + 0x9, // *..* + 0x9, // *..* + 0x6, // .**. + +// 0x56, V + + 0x11, // *...* + 0x11, // *...* + 0x11, // *...* + 0x0A, // .*.*. + 0x04, // ..*.. + +// 0x57, W + + 0x11, // *...* + 0x11, // *...* + 0x11, // *...* + 0x15, // *.*.* + 0x1B, // **.** + +// 0x58, X + + 0x9, // *..* + 0x9, // *..* + 0x6, // .**. + 0x9, // *..* + 0x9, // *..* + +// 0x59, Y + + 0x11, // *...* + 0x0A, // .*.*. + 0x04, // ..*.. + 0x04, // ..*.. + 0x04, // ..*.. + +// 0x5A, Z + + 0xF, // **** + 0x1, // ...* + 0x6, // .**. + 0x8, // *... + 0xF, // **** + +// 0x5B, [ + + 0xE, // ***. + 0x8, // *... + 0x8, // *... + 0x8, // *... + 0xE, // ***. + +// 0x5C, Backslash + + 0x8, // *... + 0xC, // **.. + 0x6, // .**. + 0x3, // ..** + 0x1, // ...* + +// 0x5D, ] + + 0x7, // .*** + 0x1, // ...* + 0x1, // ...* + 0x1, // ...* + 0x7, // .*** + +// 0x5E, ^ + + 0x6, // .**. + 0x9, // *..* + 0x0, // .... + 0x0, // .... + 0x0, // .... + +// 0x5F, _ + + 0x0, // .... + 0x0, // .... + 0x0, // .... + 0x0, // .... + 0xF, // **** +} ; diff --git a/examples/Gertboard/7segments.c b/examples/Gertboard/7segments.c new file mode 100644 index 0000000..8797e49 --- /dev/null +++ b/examples/Gertboard/7segments.c @@ -0,0 +1,221 @@ +/* + * 7segments.c: + * Simple test program to see if we can drive a 7-segment LED + * display using the GPIO and little else on the Raspberry Pi + * + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + */ + +#undef PHOTO_HACK + +#include + +#include +#include +#include +#include + +/* + * Segment mapping + * + * --a-- + * | | + * f b + * | | + * --g-- + * | | + * e c + * | | + * --d-- p + */ + +// GPIO Pin Mapping + +static int digits [6] = { 7, 11, 10, 13, 12, 14 } ; +static int segments [7] = { 6, 5, 4, 3, 2, 1, 0 } ; + + +static const int segmentDigits [] = +{ +// a b c d e f g Segments +// 6 5 4 3 2 1 0, // wiringPi pin No. + + 1, 1, 1, 1, 1, 1, 0, // 0 + 0, 1, 1, 0, 0, 0, 0, // 1 + 1, 1, 0, 1, 1, 0, 1, // 2 + 1, 1, 1, 1, 0, 0, 1, // 3 + 0, 1, 1, 0, 0, 1, 1, // 4 + 1, 0, 1, 1, 0, 1, 1, // 5 + 1, 0, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 0, 0, 0, 0, // 7 + 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 0, 1, 1, // 9 + 1, 1, 1, 0, 1, 1, 1, // A + 0, 0, 1, 1, 1, 1, 1, // b + 1, 0, 0, 1, 1, 1, 0, // C + 0, 1, 1, 1, 1, 0, 1, // d + 1, 0, 0, 1, 1, 1, 1, // E + 1, 0, 0, 0, 1, 1, 1, // F + 0, 0, 0, 0, 0, 0, 0, // blank +} ; + + +// display: +// A global variable which is written to by the main program and +// read from by the thread that updates the display. Only the first +// 6 characters are used. + +char display [8] ; + + +/* + * displayDigits: + * This is our thread that's run concurrently with the main program. + * Essentially sit in a loop, parsing and displaying the data held in + * the "display" global. + ********************************************************************************* + */ + +PI_THREAD (displayDigits) +{ + int digit, segment ; + int index, d, segVal ; + + piHiPri (50) ; + + for (;;) + { + for (digit = 0 ; digit < 6 ; ++digit) + { + for (segment = 0 ; segment < 7 ; ++segment) + { + d = toupper (display [digit]) ; + /**/ if ((d >= '0') && (d <= '9')) // Digit + index = d - '0' ; + else if ((d >= 'A') && (d <= 'F')) // Hex + index = d - 'A' + 10 ; + else + index = 16 ; // Blank + + segVal = segmentDigits [index * 7 + segment] ; + + digitalWrite (segments [segment], segVal) ; + } + digitalWrite (digits [digit], 1) ; + delay (2) ; + digitalWrite (digits [digit], 0) ; + } + } +} + + +/* + * setup: + * Initialise the hardware and start the thread + ********************************************************************************* + */ + +void setup (void) +{ + int i, c ; + + wiringPiSetup () ; + +// 7 segments + + for (i = 0 ; i < 7 ; ++i) + { digitalWrite (segments [i], 0) ; pinMode (segments [i], OUTPUT) ; } + +// 6 digits + + for (i = 0 ; i < 6 ; ++i) + { digitalWrite (digits [i], 0) ; pinMode (digits [i], OUTPUT) ; } + + strcpy (display, " ") ; + piThreadCreate (displayDigits) ; + delay (10) ; // Just to make sure it's started + +// Quick countdown LED test sort of thing + + c = 999999 ; + for (i = 0 ; i < 10 ; ++i) + { + sprintf (display, "%06d", c) ; + delay (400) ; + c -= 111111 ; + } + + strcpy (display, " ") ; + delay (400) ; + +#ifdef PHOTO_HACK + sprintf (display, "%s", "123456") ; + for (;;) + delay (1000) ; +#endif + +} + + +/* + * teenager: + * No explanation needed. (Nor one given!) + ********************************************************************************* + */ + +void teenager (void) +{ + char *message = " feedbeef babe cafe b00b " ; + int i ; + + for (i = 0 ; i < strlen (message) - 4 ; ++i) + { + strncpy (display, &message [i], 6) ; + delay (200) ; + } + delay (1000) ; + for (i = 0 ; i < 3 ; ++i) + { + strcpy (display, " ") ; + delay (150) ; + strcpy (display, " b00b ") ; + delay (250) ; + } + delay (1000) ; + strcpy (display, " ") ; + delay (1000) ; +} + + +/* + ********************************************************************************* + * main: + * Let the fun begin + ********************************************************************************* + */ + +int main (void) +{ + struct tm *t ; + time_t tim ; + + setup () ; + teenager () ; + + tim = time (NULL) ; + for (;;) + { + while (time (NULL) == tim) + delay (5) ; + + tim = time (NULL) ; + t = localtime (&tim) ; + + sprintf (display, "%02d%02d%02d", t->tm_hour, t->tm_min, t->tm_sec) ; + + delay (500) ; + } + + return 0 ; +} diff --git a/examples/Gertboard/Makefile b/examples/Gertboard/Makefile new file mode 100644 index 0000000..1939ad6 --- /dev/null +++ b/examples/Gertboard/Makefile @@ -0,0 +1,78 @@ +# +# Makefile: +# Gertboard - Examples using wiringPi +# +# Copyright (c) 2013 Gordon Henderson +################################################################################# + +ifneq ($V,1) +Q ?= @ +endif + +#DEBUG = -g -O0 +DEBUG = -O3 +CC = gcc +INCLUDE = -I/usr/local/include +CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe + +LDFLAGS = -L/usr/local/lib +LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm + +# Should not alter anything below this line +############################################################################### + +SRC = gertboard.c \ + buttons.c 7segments.c \ + voltmeter.c temperature.c vumeter.c \ + record.c + +OBJ = $(SRC:.c=.o) + +BINS = $(SRC:.c=) + +all: $(BINS) + +gertboard: gertboard.o + $Q echo [link] + $Q $(CC) -o $@ gertboard.o $(LDFLAGS) $(LDLIBS) + +buttons: buttons.o + $Q echo [link] + $Q $(CC) -o $@ buttons.o $(LDFLAGS) $(LDLIBS) + +7segments: 7segments.o + $Q echo [link] + $Q $(CC) -o $@ 7segments.o $(LDFLAGS) $(LDLIBS) + +voltmeter: voltmeter.o + $Q echo [link] + $Q $(CC) -o $@ voltmeter.o $(LDFLAGS) $(LDLIBS) + +temperature: temperature.o + $Q echo [link] + $Q $(CC) -o $@ temperature.o $(LDFLAGS) $(LDLIBS) + +vumeter: vumeter.o + $Q echo [link] + $Q $(CC) -o $@ vumeter.o $(LDFLAGS) $(LDLIBS) + +record: record.o + $Q echo [link] + $Q $(CC) -o $@ record.o $(LDFLAGS) $(LDLIBS) + +.c.o: + $Q echo [CC] $< + $Q $(CC) -c $(CFLAGS) $< -o $@ + +clean: + $Q echo [Clean] + $Q rm -f $(OBJ) *~ core tags $(BINS) + +tags: $(SRC) + $Q echo [ctags] + $Q ctags $(SRC) + +depend: + makedepend -Y $(SRC) + +# DO NOT DELETE diff --git a/examples/Gertboard/buttons.c b/examples/Gertboard/buttons.c new file mode 100644 index 0000000..5f76764 --- /dev/null +++ b/examples/Gertboard/buttons.c @@ -0,0 +1,83 @@ +/* + * buttons.c: + * Read the Gertboard buttons. Each one will act as an on/off + * tiggle switch for 3 different LEDs + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include + +// Array to keep track of our LEDs + +int leds [] = { 0, 0, 0 } ; + +// scanButton: +// See if a button is pushed, if so, then flip that LED and +// wait for the button to be let-go + +void scanButton (int button) +{ + if (digitalRead (button) == HIGH) // Low is pushed + return ; + + leds [button] ^= 1 ; // Invert state + digitalWrite (4 + button, leds [button]) ; + + while (digitalRead (button) == LOW) // Wait for release + delay (10) ; +} + +int main (void) +{ + int i ; + + printf ("Raspberry Pi Gertboard Button Test\n") ; + + wiringPiSetup () ; + +// Setup the outputs: +// Pins 3, 4, 5, 6 and 7 output: +// We're not using 3 or 4, but make sure they're off anyway +// (Using same hardware config as blink12.c) + + for (i = 3 ; i < 8 ; ++i) + { + pinMode (i, OUTPUT) ; + digitalWrite (i, 0) ; + } + +// Setup the inputs + + for (i = 0 ; i < 3 ; ++i) + { + pinMode (i, INPUT) ; + pullUpDnControl (i, PUD_UP) ; + leds [i] = 0 ; + } + + for (;;) + { + for (i = 0 ; i < 3 ; ++i) + scanButton (i) ; + delay (1) ; + } +} diff --git a/examples/Gertboard/gertboard.c b/examples/Gertboard/gertboard.c new file mode 100644 index 0000000..aefcb12 --- /dev/null +++ b/examples/Gertboard/gertboard.c @@ -0,0 +1,96 @@ +/* + * gertboard.c: + * Simple test for the SPI bus on the Gertboard + * + * Hardware setup: + * D/A port 0 jumpered to A/D port 0. + * + * We output a sine wave on D/A port 0 and sample A/D port 0. We then + * plot the input value on the terminal as a sort of vertical scrolling + * oscilloscipe. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include + +// Gertboard D to A is an 8-bit unit. + +#define B_SIZE 256 + +#include +#include + +int main (void) +{ + double angle ; + int i, inputValue ; + int buffer [B_SIZE] ; + int cols ; + struct winsize w ; + + + printf ("Raspberry Pi Gertboard SPI test program\n") ; + printf ("=======================================\n") ; + + ioctl (fileno (stdin), TIOCGWINSZ, &w); + cols = w.ws_col - 2 ; + +// Always initialise wiringPi. Use wiringPiSys() if you don't need +// (or want) to run as root + + wiringPiSetupSys () ; + +// Initialise the Gertboard analog hardware at pin 100 + + gertboardAnalogSetup (100) ; + +// Generate a Sine Wave and store in our buffer + + for (i = 0 ; i < B_SIZE ; ++i) + { + angle = ((double)i / (double)B_SIZE) * M_PI * 2.0 ; + buffer [i] = (int)rint ((sin (angle)) * 127.0 + 128.0) ; + } + +// Loop, output the sine wave on analog out port 0, read it into A-D port 0 +// and display it on the screen + + for (;;) + { + for (i = 0 ; i < B_SIZE ; ++i) + { + analogWrite (100, buffer [i]) ; + + inputValue = analogRead (100) ; + +// We don't need to wory about the scale or sign - the analog hardware is +// a 10-bit value, so 0-1023. Just scale this to our terminal + + printf ("%*s\n", (inputValue * cols) / 1023, "*") ; + delay (2) ; + } + } + + return 0 ; +} diff --git a/examples/Gertboard/record.c b/examples/Gertboard/record.c new file mode 100644 index 0000000..71d8718 --- /dev/null +++ b/examples/Gertboard/record.c @@ -0,0 +1,60 @@ +/* + * record.c: + * Record some audio via the Gertboard + * + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + */ + +#include +#include + +#include +#include + +#define B_SIZE 40000 + +int main () +{ + int i ; + struct timeval tStart, tEnd, tTaken ; + unsigned char buffer [B_SIZE] ; + + printf ("\n") ; + printf ("Gertboard demo: Recorder\n") ; + printf ("========================\n") ; + +// Always initialise wiringPi. Use wiringPiSys() if you don't need +// (or want) to run as root + + wiringPiSetupSys () ; + +// Initialise the Gertboard analog hardware at pin 100 + + gertboardAnalogSetup (100) ; + + gettimeofday (&tStart, NULL) ; + + for (i = 0 ; i < B_SIZE ; ++i) + buffer [i] = analogRead (100) >> 2 ; + + gettimeofday (&tEnd, NULL) ; + + timersub (&tEnd, &tStart, &tTaken) ; + + printf ("Time taken for %d reads: %ld.%ld\n", B_SIZE, tTaken.tv_sec, tTaken.tv_usec) ; + + gettimeofday (&tStart, NULL) ; + + for (i = 0 ; i < B_SIZE ; ++i) + analogWrite (100, buffer [i]) ; + + gettimeofday (&tEnd, NULL) ; + + timersub (&tEnd, &tStart, &tTaken) ; + + printf ("Time taken for %d writes: %ld.%ld\n", B_SIZE, tTaken.tv_sec, tTaken.tv_usec) ; + + return 0 ; +} + diff --git a/examples/Gertboard/temperature.c b/examples/Gertboard/temperature.c new file mode 100644 index 0000000..5985a12 --- /dev/null +++ b/examples/Gertboard/temperature.c @@ -0,0 +1,78 @@ +/* + * temperature.c: + * Demonstrate use of the Gertboard A to D converter to make + * a simple thermometer using the LM35. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include + +#include +#include + +int main () +{ + int x1, x2 ; + double v1, v2 ; + + printf ("\n") ; + printf ("Gertboard demo: Simple Thermemeter\n") ; + printf ("==================================\n") ; + +// Always initialise wiringPi. Use wiringPiSys() if you don't need +// (or want) to run as root + + wiringPiSetupSys () ; + +// Initialise the Gertboard analog hardware at pin 100 + + gertboardAnalogSetup (100) ; + + printf ("\n") ; + printf ("| Channel 0 | Channel 1 | Temperature 1 | Temperature 2 |\n") ; + + for (;;) + { + +// Read the 2 channels: + + x1 = analogRead (100) ; + x2 = analogRead (101) ; + +// Convert to a voltage: + + v1 = (double)x1 / 1023.0 * 3.3 ; + v2 = (double)x2 / 1023.0 * 3.3 ; + +// Print + + printf ("| %6.3f | %6.3f |", v1, v2) ; + +// Print Temperature of both channels by converting the LM35 reading +// to a temperature. Fortunately these are easy: 0.01 volts per C. + + printf (" %4.1f | %4.1f |\r", v1 * 100.0, v2 * 100.0) ; + fflush (stdout) ; + } + + return 0 ; +} + diff --git a/examples/Gertboard/voltmeter.c b/examples/Gertboard/voltmeter.c new file mode 100644 index 0000000..c4d2113 --- /dev/null +++ b/examples/Gertboard/voltmeter.c @@ -0,0 +1,73 @@ +/* + * voltmeter.c: + * Demonstrate use of the Gertboard A to D converter to make + * a simple voltmeter. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include + +#include +#include + +int main () +{ + int x1, x2 ; + double v1, v2 ; + + printf ("\n") ; + printf ("Gertboard demo: Simple Voltmeters\n") ; + printf ("=================================\n") ; + +// Always initialise wiringPi. Use wiringPiSys() if you don't need +// (or want) to run as root + + wiringPiSetupSys () ; + +// Initialise the Gertboard analog hardware at pin 100 + + gertboardAnalogSetup (100) ; + + printf ("\n") ; + printf ("| Channel 0 | Channel 1 |\n") ; + + for (;;) + { + +// Read the 2 channels: + + x1 = analogRead (100) ; + x2 = analogRead (101) ; + +// Convert to a voltage: + + v1 = (double)x1 / 1023.0 * 3.3 ; + v2 = (double)x2 / 1023.0 * 3.3 ; + +// Print + + printf ("| %6.3f | %6.3f |\r", v1, v2) ; + fflush (stdout) ; + } + + return 0 ; +} + diff --git a/examples/Gertboard/vumeter.c b/examples/Gertboard/vumeter.c new file mode 100644 index 0000000..9643ace --- /dev/null +++ b/examples/Gertboard/vumeter.c @@ -0,0 +1,152 @@ +/* + * vumeter.c: + * Simple VU meter + * + * Heres the theory: + * We will sample at 4000 samples/sec and put the data into a + * low-pass filter with a depth of 1000 samples. This will give + * us 1/4 a second of lag on the signal, but I think it might + * produce a more pleasing output. + * + * The input of the microphone should be at mid-pont with no + * sound input, but we might have to sample that too, to get + * our reference zero... + * + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + */ + +#include +#include +#include + +#include +#include + +#ifndef TRUE +#define TRUE (1==1) +#define FALSE (!TRUE) +#endif + +#define B_SIZE 1000 +#define S_SIZE 128 + +static int buffer [B_SIZE] ; +static int bPtr = 0 ; + +/* + * ledPercent: + * Output the given value as a percentage on the LEDs + ********************************************************************************* + */ + +static void ledPercent (int percent) +{ + unsigned int output = 0 ; + + if (percent > 11) output |= 0x01 ; + if (percent > 22) output |= 0x02 ; + if (percent > 33) output |= 0x04 ; + if (percent > 44) output |= 0x08 ; + if (percent > 55) output |= 0x10 ; + if (percent > 66) output |= 0x20 ; + if (percent > 77) output |= 0x40 ; + if (percent > 88) output |= 0x80 ; + + digitalWriteByte (output) ; +} + +static unsigned int tPeriod, tNextSampleTime ; + +/* + * sample: + * Get a sample from the Gertboard. If not enough time has elapsed + * since the last sample, then wait... + ********************************************************************************* + */ + +static void sample (void) +{ + unsigned int tFuture ; + +// Calculate the future sample time + + tFuture = tPeriod + tNextSampleTime ; + +// Wait until the next sample time + + while (micros () < tNextSampleTime) + ; + + buffer [bPtr] = gertboardAnalogRead (0) ; + + tNextSampleTime = tFuture ; +} + + +int main () +{ + int quietLevel, min, max ; + int i, sum ; + unsigned int tStart, tEnd ; + + printf ("\n") ; + printf ("Gertboard demo: VU Meter\n") ; + printf ("========================\n") ; + + wiringPiSetup () ; + gertboardSPISetup () ; + + ledPercent (0) ; + for (i = 0 ; i < 8 ; ++i) + pinMode (i, OUTPUT) ; + + for (bPtr = 0 ; bPtr < B_SIZE ; ++bPtr) + buffer [bPtr] = 99 ; + + tPeriod = 1000000 / 1000 ; + + printf ("Shhhh.... ") ; fflush (stdout) ; + delay (1000) ; + printf ("Sampling quiet... ") ; fflush (stdout) ; + + tStart = micros () ; + + tNextSampleTime = micros () ; + for (bPtr = 0 ; bPtr < B_SIZE ; ++bPtr) + sample () ; + + tEnd = micros () ; + + quietLevel = 0 ; + max = 0 ; + min = 1024 ; + for (i = 0 ; i < B_SIZE ; ++i) + { + quietLevel += buffer [i] ; + if (buffer [i] > max) max = buffer [i] ; + if (buffer [i] < min) min = buffer [i] ; + } + quietLevel /= B_SIZE ; + + printf ("Done. Quiet level is: %d [%d:%d] [%d:%d]\n", quietLevel, min, max, quietLevel - min, max - quietLevel) ; + + printf ("Time taken for %d reads: %duS\n", B_SIZE, tEnd - tStart) ; + + for (bPtr = 0 ;;) + { + sample () ; + sum = 0 ; + for (i = 0 ; i < S_SIZE ; ++i) + sum += buffer [i] ; + sum /= S_SIZE ; + sum = abs (quietLevel - sum) ; + sum = (sum * 1000) / quietLevel ; + ledPercent (sum) ; + if (++bPtr > S_SIZE) + bPtr = 0 ; + } + + + return 0 ; +} diff --git a/examples/PiFace/Makefile b/examples/PiFace/Makefile new file mode 100644 index 0000000..f937c14 --- /dev/null +++ b/examples/PiFace/Makefile @@ -0,0 +1,88 @@ +# +# Makefile: +# wiringPi - A "wiring" library for the Raspberry Pi +# https://projects.drogon.net/wiring-pi +# +# Copyright (c) 2012 Gordon Henderson +################################################################################# +# This file is part of wiringPi: +# A "wiring" library for the Raspberry Pi +# +# wiringPi is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# wiringPi is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with wiringPi. If not, see . +################################################################################# + +ifneq ($V,1) +Q ?= @ +endif + +#DEBUG = -g -O0 +DEBUG = -O3 +CC = gcc +INCLUDE = -I/usr/local/include +CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe + +LDFLAGS = -L/usr/local/lib +LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm + +# Should not alter anything below this line +############################################################################### + +SRC = blink.c buttons.c reaction.c ladder.c metro.c motor.c + +OBJ = $(SRC:.c=.o) + +BINS = $(SRC:.c=) + +all: $(BINS) + +blink: blink.o + $Q echo [link] + $Q $(CC) -o $@ blink.o $(LDFLAGS) $(LDLIBS) + +buttons: buttons.o + $Q echo [link] + $Q $(CC) -o $@ buttons.o $(LDFLAGS) $(LDLIBS) + +reaction: reaction.o + $Q echo [link] + $Q $(CC) -o $@ reaction.o $(LDFLAGS) $(LDLIBS) + +ladder: ladder.o + $Q echo [link] + $Q $(CC) -o $@ ladder.o $(LDFLAGS) $(LDLIBS) + +metro: metro.o + $Q echo [link] + $Q $(CC) -o $@ metro.o $(LDFLAGS) $(LDLIBS) + +motor: motor.o + $Q echo [link] + $Q $(CC) -o $@ motor.o $(LDFLAGS) $(LDLIBS) + +.c.o: + $Q echo [CC] $< + $Q $(CC) -c $(CFLAGS) $< -o $@ + +clean: + $Q echo "[Clean]" + $Q rm -f $(OBJ) *~ core tags $(BINS) + +tags: $(SRC) + $Q echo [ctags] + $Q ctags $(SRC) + +depend: + makedepend -Y $(SRC) + +# DO NOT DELETE diff --git a/examples/PiFace/blink.c b/examples/PiFace/blink.c new file mode 100644 index 0000000..ffb8a2e --- /dev/null +++ b/examples/PiFace/blink.c @@ -0,0 +1,59 @@ +/* + * blink.c: + * Simple "blink" test for the PiFace interface board. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include + +#include +#include + +// Use 200 as the pin-base for the PiFace board, and pick a pin +// for the LED that's not connected to a relay + +#define PIFACE 200 +#define LED (PIFACE+2) + +int main (int argc, char *argv []) +{ + printf ("Raspberry Pi PiFace Blink\n") ; + printf ("=========================\n") ; + +// Always initialise wiringPi. Use wiringPiSys() if you don't need +// (or want) to run as root + + wiringPiSetupSys () ; + +// Setup the PiFace board + + piFaceSetup (PIFACE) ; + + for (;;) + { + digitalWrite (LED, HIGH) ; // On + delay (500) ; // mS + digitalWrite (LED, LOW) ; // Off + delay (500) ; + } + + return 0 ; +} diff --git a/examples/PiFace/buttons.c b/examples/PiFace/buttons.c new file mode 100644 index 0000000..147a4bd --- /dev/null +++ b/examples/PiFace/buttons.c @@ -0,0 +1,103 @@ +/* + * buttons.c: + * Simple test for the PiFace interface board. + * + * Read the buttons and output the same to the LEDs + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include + +#include +#include + +int outputs [4] = { 0,0,0,0 } ; + +// Use 200 as the pin-base for the PiFace board + +#define PIFACE_BASE 200 + + +/* + * scanButton: + * Read the guiven button - if it's pressed, then flip the state + * of the correspoinding output pin + ********************************************************************************* + */ + +void scanButton (int button) +{ + if (digitalRead (PIFACE_BASE + button) == LOW) + { + outputs [button] ^= 1 ; + digitalWrite (PIFACE_BASE + button, outputs [button]) ; + printf ("Button %d pushed - output now: %s\n", + button, (outputs [button] == 0) ? "Off" : "On") ; + } + + while (digitalRead (PIFACE_BASE + button) == LOW) + delay (1) ; +} + + +/* + * start here + ********************************************************************************* + */ + +int main (void) +{ + int pin, button ; + + printf ("Raspberry Pi wiringPi + PiFace test program\n") ; + printf ("===========================================\n") ; + printf ("\n") ; + printf ( +"This program reads the buttons and uses them to toggle the first 4\n" +"outputs. Push a button once to turn an output on, and push it again to\n" +"turn it off again.\n\n") ; + +// Always initialise wiringPi. Use wiringPiSys() if you don't need +// (or want) to run as root + + wiringPiSetupSys () ; + + piFaceSetup (PIFACE_BASE) ; + +// Enable internal pull-ups & start with all off + + for (pin = 0 ; pin < 8 ; ++pin) + { + pullUpDnControl (PIFACE_BASE + pin, PUD_UP) ; + digitalWrite (PIFACE_BASE + pin, 0) ; + } + +// Loop, scanning the buttons + + for (;;) + { + for (button = 0 ; button < 4 ; ++button) + scanButton (button) ; + delay (5) ; + } + + return 0 ; +} diff --git a/examples/PiFace/ladder.c b/examples/PiFace/ladder.c new file mode 100644 index 0000000..4f08a6f --- /dev/null +++ b/examples/PiFace/ladder.c @@ -0,0 +1,337 @@ +/* + * ladder.c: + * + * Gordon Henderson, June 2012 + *********************************************************************** + */ + +#include +#include +#include +#include + +#include +#include + +#ifndef TRUE +# define TRUE (1==1) +# define FALSE (1==2) +#endif + +#undef DEBUG + +#define NUM_LEDS 8 + + +// Map the LEDs to the hardware pins +// using PiFace pin numbers here + +#define PIFACE 200 + +const int ledMap [NUM_LEDS] = +{ +// 0, 1, 2, 3, 4, 5, 6, 7, 8 + 200, 201, 202, 203, 204, 205, 206, 207 +} ; + + +// Some constants for our circuit simulation + +const double vBatt = 9.0 ; // Volts (ie. a PP3) +const double capacitor = 0.001 ; // 1000uF +const double rCharge = 2200.0 ; // ohms +const double rDischarge = 68000.0 ; // ohms +const double timeInc = 0.01 ; // Seconds + +double vCharge, vCap, vCapLast ; + + + +/* + * setup: + * Program the GPIO correctly and initialise the lamps + *********************************************************************** + */ + +void setup (void) +{ + int i ; + + wiringPiSetupSys () ; + + if (piFaceSetup (200) == -1) + exit (1) ; + +// Enable internal pull-ups + + for (i = 0 ; i < 8 ; ++i) + pullUpDnControl (PIFACE + i, PUD_UP) ; + +// Calculate the actual charging voltage - standard calculation of +// vCharge = r2 / (r1 + r2) * vBatt +// +// +// -----+--- vBatt +// | +// R1 +// | +// +---+---- vCharge +// | | +// R2 C +// | | +// -----+---+----- + + vCharge = rDischarge / (rCharge + rDischarge) * vBatt ; + +// Start with no charge + + vCap = vCapLast = 0.0 ; +} + + +/* + * introLeds + * Put a little pattern on the LEDs to start with + ********************************************************************************* + */ + +void introLeds (void) +{ + int i, j ; + + + printf ("Pi Ladder\n") ; + printf ("=========\n\n") ; + printf (" vBatt: %6.2f volts\n", vBatt) ; + printf (" rCharge: %6.0f ohms\n", rCharge) ; + printf (" rDischarge: %6.0f ohms\n", rDischarge) ; + printf (" vCharge: %6.2f volts\n", vCharge) ; + printf (" capacitor: %6.0f uF\n", capacitor * 1000.0) ; + +// Flash 3 times: + + for (j = 0 ; j < 3 ; ++j) + { + for (i = 0 ; i < NUM_LEDS ; ++i) + digitalWrite (ledMap [i], 1) ; + delay (500) ; + for (i = 0 ; i < NUM_LEDS ; ++i) + digitalWrite (ledMap [i], 0) ; + delay (100) ; + } + +// All On + + for (i = 0 ; i < NUM_LEDS ; ++i) + digitalWrite (ledMap [i], 1) ; + delay (500) ; + +// Countdown... + + for (i = NUM_LEDS - 1 ; i >= 0 ; --i) + { + digitalWrite (ledMap [i], 0) ; + delay (100) ; + } + delay (500) ; +} + + +/* + * winningLeds + * Put a little pattern on the LEDs to start with + ********************************************************************************* + */ + +void winningLeds (void) +{ + int i, j ; + +// Flash 3 times: + + for (j = 0 ; j < 3 ; ++j) + { + for (i = 0 ; i < NUM_LEDS ; ++i) + digitalWrite (ledMap [i], 1) ; + delay (500) ; + for (i = 0 ; i < NUM_LEDS ; ++i) + digitalWrite (ledMap [i], 0) ; + delay (100) ; + } + +// All On + + for (i = 0 ; i < NUM_LEDS ; ++i) + digitalWrite (ledMap [i], 1) ; + delay (500) ; + +// Countup... + + for (i = 0 ; i < NUM_LEDS ; ++i) + { + digitalWrite (ledMap [i], 0) ; + delay (100) ; + } + delay (500) ; +} + + +/* + * chargeCapacitor: dischargeCapacitor: + * Add or remove charge to the capacitor. + * Standard capacitor formulae. + ********************************************************************************* + */ + +void chargeCapacitor (void) +{ + vCap = (vCapLast - vCharge) * + exp (- timeInc / (rCharge * capacitor)) + vCharge ; + +#ifdef DEBUG + printf ("+vCap: %7.4f\n", vCap) ; +#endif + + vCapLast = vCap ; +} + +void dischargeCapacitor (void) +{ + vCap = vCapLast * + exp (- timeInc / (rDischarge * capacitor)) ; + +#ifdef DEBUG + printf ("-vCap: %7.4f\n", vCap) ; +#endif + + vCapLast = vCap ; +} + + +/* + * ledBargraph: + * Output the supplied number as a bargraph on the LEDs + ********************************************************************************* + */ + +void ledBargraph (double value, int topLedOn) +{ + int topLed = (int)floor (value / vCharge * (double)NUM_LEDS) + 1 ; + int i ; + + if (topLed > NUM_LEDS) + topLed = NUM_LEDS ; + + if (!topLedOn) + --topLed ; + + for (i = 0 ; i < topLed ; ++i) + digitalWrite (ledMap [i], 1) ; + + for (i = topLed ; i < NUM_LEDS ; ++i) + digitalWrite (ledMap [i], 0) ; +} + + +/* + * ledOnAction: + * Make sure the leading LED is on and check the button + ********************************************************************************* + */ + +void ledOnAction (void) +{ + if (digitalRead (PIFACE) == LOW) + { + chargeCapacitor () ; + ledBargraph (vCap, TRUE) ; + } +} + + +/* + * ledOffAction: + * Make sure the leading LED is off and check the button + ********************************************************************************* + */ + +void ledOffAction (void) +{ + dischargeCapacitor () ; + +// Are we still pushing the button? + + if (digitalRead (PIFACE) == LOW) + { + vCap = vCapLast = 0.0 ; + ledBargraph (vCap, FALSE) ; + +// Wait until we release the button + + while (digitalRead (PIFACE) == LOW) + delay (10) ; + } +} + + +/* + *********************************************************************** + * The main program + *********************************************************************** + */ + +int main (void) +{ + unsigned int then, ledOnTime, ledOffTime ; + unsigned int ourDelay = (int)(1000.0 * timeInc) ; + + setup () ; + introLeds () ; + +// Setup the LED times - TODO reduce the ON time as the game progresses + + ledOnTime = 1000 ; + ledOffTime = 1000 ; + +// This is our Gate/Squarewave loop + + for (;;) + { + +// LED ON: + + (void)ledBargraph (vCap, TRUE) ; + then = millis () + ledOnTime ; + while (millis () < then) + { + ledOnAction () ; + delay (ourDelay) ; + } + +// Have we won yet? +// We need vCap to be in the top NUM_LEDS of the vCharge + + if (vCap > ((double)(NUM_LEDS - 1) / (double)NUM_LEDS * vCharge)) // Woo hoo! + { + winningLeds () ; + while (digitalRead (PIFACE) == HIGH) + delay (10) ; + while (digitalRead (PIFACE) == LOW) + delay (10) ; + vCap = vCapLast = 0.0 ; + } + +// LED OFF: + + (void)ledBargraph (vCap, FALSE) ; + then = millis () + ledOffTime ; + while (millis () < then) + { + ledOffAction () ; + delay (ourDelay) ; + } + + } + + return 0 ; +} diff --git a/examples/PiFace/metro.c b/examples/PiFace/metro.c new file mode 100644 index 0000000..a4a8c1d --- /dev/null +++ b/examples/PiFace/metro.c @@ -0,0 +1,111 @@ +/* + * metronome.c: + * Simple test for the PiFace interface board. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#include +#include + +#define PIFACE 200 + +/* + * middleA: + * Play middle A (on the relays - yea!) + ********************************************************************************* + */ + +static void middleA (void) +{ + unsigned int next ; + + for (;;) + { + next = micros () + 1136 ; + digitalWrite (PIFACE + 0, 0) ; + digitalWrite (PIFACE + 1, 0) ; + while (micros () < next) + delayMicroseconds (1) ; + + next = micros () + 1137 ; + digitalWrite (PIFACE + 0, 1) ; + digitalWrite (PIFACE + 1, 1) ; + while (micros () < next) + delayMicroseconds (1) ; + + } +} + + +int main (int argc, char *argv []) +{ + int bpm, msPerBeat, state = 0 ; + unsigned int end ; + + printf ("Raspberry Pi PiFace Metronome\n") ; + printf ("=============================\n") ; + + piHiPri (50) ; + + wiringPiSetupSys () ; // Needed for timing functions + piFaceSetup (PIFACE) ; + + if (argc != 2) + { + printf ("Usage: %s \n", argv [0]) ; + exit (1) ; + } + + if (strcmp (argv [1], "a") == 0) + middleA () ; + + bpm = atoi (argv [1]) ; + + if ((bpm < 40) || (bpm > 208)) + { + printf ("%s range is 40 through 208 beats per minute\n", argv [0]) ; + exit (1) ; + } + + msPerBeat = 60000 / bpm ; + +// Main loop: +// Put some random LED pairs up for a few seconds, then blank ... + + for (;;) + { + end = millis () + msPerBeat ; + + digitalWrite (PIFACE + 0, state) ; + digitalWrite (PIFACE + 1, state) ; + + while (millis () < end) + delayMicroseconds (500) ; + + state ^= 1 ; + } + + return 0 ; +} diff --git a/examples/PiFace/motor.c b/examples/PiFace/motor.c new file mode 100644 index 0000000..14f5539 --- /dev/null +++ b/examples/PiFace/motor.c @@ -0,0 +1,120 @@ +/* + * motor.c: + * Use the PiFace board to demonstrate an H bridge + * circuit via the 2 relays. + * Then add on an external transsitor to help with PWM. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#include +#include +#include + +int outputs [2] = { 0,0 } ; + +#define PIFACE_BASE 200 +#define PWM_OUT_PIN 204 +#define PWM_UP 202 +#define PWM_DOWN 203 + +void scanButton (int button) +{ + if (digitalRead (PIFACE_BASE + button) == LOW) + { + outputs [button] ^= 1 ; + digitalWrite (PIFACE_BASE + button, outputs [button]) ; + printf ("Button %d pushed - output now: %s\n", + button, (outputs [button] == 0) ? "Off" : "On") ; + } + + while (digitalRead (PIFACE_BASE + button) == LOW) + delay (1) ; +} + + +int main (void) +{ + int pin, button ; + int pwmValue = 0 ; + + printf ("Raspberry Pi PiFace - Motor control\n") ; + printf ("==================================\n") ; + printf ("\n") ; + printf ( +"This program is designed to be used with a motor connected to the relays\n" +"in an H-Bridge type configuration with optional speeed control via PWM.\n" +"\n" +"Use the leftmost buttons to turn each relay on and off, and the rigthmost\n" +"buttons to increase ot decrease the PWM output on the control pin (pin\n" +"4)\n\n") ; + + wiringPiSetup () ; + piFaceSetup (PIFACE_BASE) ; + softPwmCreate (PWM_OUT_PIN, 100, 100) ; + +// Enable internal pull-ups & start with all off + + for (pin = 0 ; pin < 8 ; ++pin) + { + pullUpDnControl (PIFACE_BASE + pin, PUD_UP) ; + digitalWrite (PIFACE_BASE + pin, 0) ; + } + + for (;;) + { + for (button = 0 ; button < 2 ; ++button) + scanButton (button) ; + + if (digitalRead (PWM_UP) == LOW) + { + pwmValue += 10 ; + if (pwmValue > 100) + pwmValue = 100 ; + + softPwmWrite (PWM_OUT_PIN, pwmValue) ; + printf ("PWM -> %3d\n", pwmValue) ; + + while (digitalRead (PWM_UP) == LOW) + delay (5) ; + } + + if (digitalRead (PWM_DOWN) == LOW) + { + pwmValue -= 10 ; + if (pwmValue < 0) + pwmValue = 0 ; + + softPwmWrite (PWM_OUT_PIN, pwmValue) ; + printf ("PWM -> %3d\n", pwmValue) ; + + while (digitalRead (PWM_DOWN) == LOW) + delay (5) ; + } + + delay (5) ; + } + + return 0 ; +} diff --git a/examples/PiFace/reaction.c b/examples/PiFace/reaction.c new file mode 100644 index 0000000..5084508 --- /dev/null +++ b/examples/PiFace/reaction.c @@ -0,0 +1,194 @@ +/* + * reaction.c: + * Simple test for the PiFace interface board. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#include +#include + + +int outputs [4] = { 0,0,0,0 } ; + +#define PIFACE 200 + +/* + * light: + * Light up the given LED - actually lights up a pair + ********************************************************************************* + */ + +void light (int led, int value) +{ + led *= 2 ; + digitalWrite (PIFACE + led + 0, value) ; + digitalWrite (PIFACE + led + 1, value) ; +} + +/* + * lightAll: + * All On or Off + ********************************************************************************* + */ + +void lightAll (int onoff) +{ + light (0, onoff) ; + light (1, onoff) ; + light (2, onoff) ; + light (3, onoff) ; +} + + +/* + * waitForNoButtons: + * Wait for all buttons to be released + ********************************************************************************* + */ + +void waitForNoButtons (void) +{ + int i, button ; + + for (;;) + { + button = 0 ; + for (i = 0 ; i < 4 ; ++i) + button += digitalRead (PIFACE + i) ; + + if (button == 4) + break ; + } +} + + +void scanButton (int button) +{ + if (digitalRead (PIFACE + button) == LOW) + { + outputs [button] ^= 1 ; + digitalWrite (PIFACE + button, outputs [button]) ; + } + + while (digitalRead (PIFACE + button) == LOW) + delay (1) ; +} + + +int main (void) +{ + int i, j ; + int led, button ; + unsigned int start, stop ; + + printf ("Raspberry Pi PiFace Reaction Timer\n") ; + printf ("==================================\n") ; + + if (piFaceSetup (PIFACE) == -1) + exit (1) ; + +// Enable internal pull-ups + + for (i = 0 ; i < 8 ; ++i) + pullUpDnControl (PIFACE + i, PUD_UP) ; + + +// Main game loop: +// Put some random LED pairs up for a few seconds, then blank ... + + for (;;) + { + printf ("Press any button to start ... \n") ; fflush (stdout) ; + + for (;;) + { + led = rand () % 4 ; + light (led, 1) ; + delay (10) ; + light (led, 0) ; + + button = 0 ; + for (j = 0 ; j < 4 ; ++j) + button += digitalRead (PIFACE + j) ; + + if (button != 4) + break ; + } + + waitForNoButtons () ; + + printf ("Wait for it ... ") ; fflush (stdout) ; + + led = rand () % 4 ; + delay (rand () % 500 + 1000) ; + light (led, 1) ; + + start = millis () ; + for (button = -1 ; button == -1 ; ) + { + for (j = 0 ; j < 4 ; ++j) + if (digitalRead (PIFACE + j) == 0) // Pushed + { + button = j ; + break ; + } + } + stop = millis () ; + button = 3 - button ; // Correct for the buttons/LEDs reversed + + light (led, 0) ; + + waitForNoButtons () ; + + light (led, 1) ; + + if (button == led) + { + printf ("You got it in %3d mS\n", stop - start) ; + } + else + { + printf ("Missed: You pushed %d - LED was %d\n", button, led) ; + for (;;) + { + light (button, 1) ; + delay (100) ; + light (button, 0) ; + delay (100) ; + i = 0 ; + for (j = 0 ; j < 4 ; ++j) + i += digitalRead (PIFACE + j) ; + if (i != 4) + break ; + } + + waitForNoButtons () ; + } + light (led, 0) ; + delay (4000) ; + } + + return 0 ; +} diff --git a/examples/PiGlow/Makefile b/examples/PiGlow/Makefile new file mode 100644 index 0000000..f182db7 --- /dev/null +++ b/examples/PiGlow/Makefile @@ -0,0 +1,82 @@ +# +# Makefile: +# wiringPi - A "wiring" library for the Raspberry Pi +# https://projects.drogon.net/wiring-pi +# +# Copyright (c) 2012-2015 Gordon Henderson +################################################################################# +# This file is part of wiringPi: +# A "wiring" library for the Raspberry Pi +# +# wiringPi is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# wiringPi is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with wiringPi. If not, see . +################################################################################# + +ifneq ($V,1) +Q ?= @ +endif + +#DEBUG = -g -O0 +DEBUG = -O3 +CC = gcc +INCLUDE = -I/usr/local/include +CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe + +LDFLAGS = -L/usr/local/lib +LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm + +# Should not alter anything below this line +############################################################################### + +SRC = piGlow0.c piGlow1.c piglow.c + +OBJ = $(SRC:.c=.o) + +BINS = $(SRC:.c=) + +all: $(BINS) + +piGlow0: piGlow0.o + $Q echo [link] + $Q $(CC) -o $@ piGlow0.o $(LDFLAGS) $(LDLIBS) + +piGlow1: piGlow1.o + $Q echo [link] + $Q $(CC) -o $@ piGlow1.o $(LDFLAGS) $(LDLIBS) + +piglow: piglow.o + $Q echo [link] + $Q $(CC) -o $@ piglow.o $(LDFLAGS) $(LDLIBS) + +.c.o: + $Q echo [CC] $< + $Q $(CC) -c $(CFLAGS) $< -o $@ + +clean: + $Q echo "[Clean]" + $Q rm -f $(OBJ) *~ core tags $(BINS) + +tags: $(SRC) + $Q echo [ctags] + $Q ctags $(SRC) + +install: piglow + $Q echo Installing piglow into /usr/local/bin + $Q cp -a piglow /usr/local/bin/piglow + $Q chmod 755 /usr/local/bin/piglow + $Q echo Done. Remember to load the I2C drivers! + +depend: + makedepend -Y $(SRC) + +# DO NOT DELETE diff --git a/examples/PiGlow/piGlow0.c b/examples/PiGlow/piGlow0.c new file mode 100644 index 0000000..d3fe4b9 --- /dev/null +++ b/examples/PiGlow/piGlow0.c @@ -0,0 +1,51 @@ +/* + * piglow.c: + * Very simple demonstration of the PiGlow board. + * This uses the SN3218 directly - soon there will be a new PiGlow + * devLib device which will handle the PiGlow board on a more easy + * to use manner... + * + * Copyright (c) 2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include + +#define LED_BASE 533 + +int main (void) +{ + int i, j ; + + wiringPiSetupSys () ; + + sn3218Setup (LED_BASE) ; + + for (;;) + { + for (i = 0 ; i < 256 ; ++i) + for (j = 0 ; j < 18 ; ++j) + analogWrite (LED_BASE + j, i) ; + + for (i = 255 ; i >= 0 ; --i) + for (j = 0 ; j < 18 ; ++j) + analogWrite (LED_BASE + j, i) ; + } +} diff --git a/examples/PiGlow/piGlow1.c b/examples/PiGlow/piGlow1.c new file mode 100644 index 0000000..a00b31e --- /dev/null +++ b/examples/PiGlow/piGlow1.c @@ -0,0 +1,258 @@ +/* + * piGlow1.c: + * Very simple demonstration of the PiGlow board. + * This uses the piGlow devLib. + * + * Copyright (c) 2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#include +#include + +#define PIGLOW_BASE 533 + +#ifndef TRUE +# define TRUE (1==1) +# define FALSE (!TRUE) +#endif + + +/* + * keypressed: clearKeypressed: + * Simple but effective ways to tell if the enter key has been pressed + ********************************************************************************* + */ + +static int keypressed (void) +{ + struct pollfd polls ; + + polls.fd = fileno (stdin) ; + polls.events = POLLIN ; + + return poll (&polls, 1, 0) != 0 ; +} + +static void clearKeypressed (void) +{ + while (keypressed ()) + (void)getchar () ; +} + + +/* + * pulseLed: + * Pulses the LED at position leg, ring from off to a max. value, + * then off again + ********************************************************************************* + */ + +static void pulseLed (int leg, int ring) +{ + int i ; + + for (i = 0 ; i < 140 ; ++i) + { + piGlow1 (leg, ring, i) ; + delay (1) ; + } + delay (10) ; + for (i = 140 ; i >= 0 ; --i) + { + piGlow1 (leg, ring, i) ; + delay (1) ; + } +} + +/* + * pulseLeg: + * Same as above, but a whole leg at a time + ********************************************************************************* + */ + +static void pulseLeg (int leg) +{ + int i ; + + for (i = 0 ; i < 140 ; ++i) + { + piGlowLeg (leg, i) ; delay (1) ; + } + delay (10) ; + for (i = 140 ; i >= 0 ; --i) + { + piGlowLeg (leg, i) ; delay (1) ; + } +} + + +/* + * pulse Ring: + * Same as above, but a whole ring at a time + ********************************************************************************* + */ + +static void pulseRing (int ring) +{ + int i ; + + for (i = 0 ; i < 140 ; ++i) + { + piGlowRing (ring, i) ; delay (1) ; + } + delay (10) ; + for (i = 140 ; i >= 0 ; --i) + { + piGlowRing (ring, i) ; delay (1) ; + } +} + +#define LEG_STEPS 3 + +static int legSequence [] = +{ + 4, 12, 99, + 99, 4, 12, + 12, 99, 4, +} ; + + +#define RING_STEPS 16 + +static int ringSequence [] = +{ + 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 64, 64, + 0, 0, 0, 64, 64, 0, + 0, 0, 64, 64, 0, 0, + 0, 64, 64, 0, 0, 0, + 64, 64, 0, 0, 0, 0, + 64, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 0, 0, + 64, 64, 0, 0, 0, 0, + 0, 64, 64, 0, 0, 0, + 0, 0, 64, 64, 0, 0, + 0, 0, 0, 64, 64, 0, + 0, 0, 0, 0, 64, 64, + 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, +} ; + +/* + * main: + * Our little demo prgoram + ********************************************************************************* + */ + +int main (void) +{ + int i ; + int step, ring, leg ; + +// Always initialise wiringPi: +// Use the Sys method if you don't need to run as root + + wiringPiSetupSys () ; + +// Initialise the piGlow devLib with our chosen pin base + + piGlowSetup (1) ; + +// LEDs, one at a time + + printf ("LEDs, one at a time\n") ; + for (; !keypressed () ;) + for (leg = 0 ; leg < 3 ; ++leg) + { + for (ring = 0 ; ring < 6 ; ++ring) + { + pulseLed (leg, ring) ; + if (keypressed ()) + break ; + } + if (keypressed ()) + break ; + } + clearKeypressed () ; + +// Rings, one at a time + + printf ("Rings, one at a time\n") ; + for (; !keypressed () ;) + for (ring = 0 ; ring < 6 ; ++ring) + { + pulseRing (ring) ; + if (keypressed ()) + break ; + } + clearKeypressed () ; + +// Legs, one at a time + + printf ("Legs, one at a time\n") ; + for (; !keypressed () ;) + for (leg = 0 ; leg < 3 ; ++leg) + { + pulseLeg (leg) ; + if (keypressed ()) + break ; + } + clearKeypressed () ; + + delay (1000) ; + +// Sequence - alternating rings, legs and random + + printf ("Sequence now\n") ; + for (; !keypressed () ;) + { + for (i = 0 ; i < 20 ; ++i) + for (step = 0 ; step < LEG_STEPS ; ++step) + { + for (leg = 0 ; leg < 3 ; ++leg) + piGlowLeg (leg, legSequence [step * 3 + leg]) ; + delay (80) ; + } + + for (i = 0 ; i < 10 ; ++i) + for (step = 0 ; step < RING_STEPS ; ++step) + { + for (ring = 0 ; ring < 6 ; ++ring) + piGlowRing (ring, ringSequence [step * 6 + ring]) ; + delay (80) ; + } + + for (i = 0 ; i < 1000 ; ++i) + { + leg = random () % 3 ; + ring = random () % 6 ; + piGlow1 (leg, ring, random () % 256) ; + delay (5) ; + piGlow1 (leg, ring, 0) ; + } + } + + return 0 ; +} diff --git a/examples/PiGlow/piglow.c b/examples/PiGlow/piglow.c new file mode 100644 index 0000000..e6a2db3 --- /dev/null +++ b/examples/PiGlow/piglow.c @@ -0,0 +1,176 @@ +/* + * piglow.c: + * Very simple demonstration of the PiGlow board. + * This uses the piGlow devLib. + * + * Copyright (c) 2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#ifndef TRUE +# define TRUE (1==1) +# define FALSE (!TRUE) +#endif + +#include +#include + +static void failUsage (void) +{ + fprintf (stderr, "Usage examples:\n") ; + fprintf (stderr, " piglow off # All off\n") ; + fprintf (stderr, " piglow red 50 # Light the 3 red LEDs to 50%%\n") ; + fprintf (stderr, " colours are: red, yellow, orange, green, blue and white\n") ; + fprintf (stderr, " piglow all 75 # Light all to 75%%\n") ; + fprintf (stderr, " piglow leg 0 25 # Light leg 0 to 25%%\n") ; + fprintf (stderr, " piglow ring 3 100 # Light ring 3 to 100%%\n") ; + fprintf (stderr, " piglow led 2 5 100 # Light the single LED on Leg 2, ring 5 to 100%%\n") ; + + exit (EXIT_FAILURE) ; +} + +static int getPercent (char *typed) +{ + int percent ; + + percent = atoi (typed) ; + if ((percent < 0) || (percent > 100)) + { + fprintf (stderr, "piglow: percent value out of range\n") ; + exit (EXIT_FAILURE) ; + } + return (percent * 255) / 100 ; +} + + +/* + * main: + * Our little demo prgoram + ********************************************************************************* + */ + +int main (int argc, char *argv []) +{ + int percent ; + int ring, leg ; + +// Always initialise wiringPi: +// Use the Sys method if you don't need to run as root + + wiringPiSetupSys () ; + +// Initialise the piGlow devLib + + piGlowSetup (FALSE) ; + + if (argc == 1) + failUsage () ; + + if ((argc == 2) && (strcasecmp (argv [1], "off") == 0)) + { + for (leg = 0 ; leg < 3 ; ++leg) + piGlowLeg (leg, 0) ; + return 0 ; + } + + if (argc == 3) + { + percent = getPercent (argv [2]) ; + + /**/ if (strcasecmp (argv [1], "red") == 0) + piGlowRing (PIGLOW_RED, percent) ; + else if (strcasecmp (argv [1], "yellow") == 0) + piGlowRing (PIGLOW_YELLOW, percent) ; + else if (strcasecmp (argv [1], "orange") == 0) + piGlowRing (PIGLOW_ORANGE, percent) ; + else if (strcasecmp (argv [1], "green") == 0) + piGlowRing (PIGLOW_GREEN, percent) ; + else if (strcasecmp (argv [1], "blue") == 0) + piGlowRing (PIGLOW_BLUE, percent) ; + else if (strcasecmp (argv [1], "white") == 0) + piGlowRing (PIGLOW_WHITE, percent) ; + else if (strcasecmp (argv [1], "all") == 0) + for (ring = 0 ; ring < 6 ; ++ring) + piGlowRing (ring, percent) ; + else + { + fprintf (stderr, "piglow: invalid colour\n") ; + exit (EXIT_FAILURE) ; + } + return 0 ; + } + + if (argc == 4) + { + /**/ if (strcasecmp (argv [1], "leg") == 0) + { + leg = atoi (argv [2]) ; + if ((leg < 0) || (leg > 2)) + { + fprintf (stderr, "piglow: leg value out of range\n") ; + exit (EXIT_FAILURE) ; + } + percent = getPercent (argv [3]) ; + piGlowLeg (leg, percent) ; + } + else if (strcasecmp (argv [1], "ring") == 0) + { + ring = atoi (argv [2]) ; + if ((ring < 0) || (ring > 5)) + { + fprintf (stderr, "piglow: ring value out of range\n") ; + exit (EXIT_FAILURE) ; + } + percent = getPercent (argv [3]) ; + piGlowRing (ring, percent) ; + } + return 0 ; + } + + if (argc == 5) + { + if (strcasecmp (argv [1], "led") != 0) + failUsage () ; + + leg = atoi (argv [2]) ; + if ((leg < 0) || (leg > 2)) + { + fprintf (stderr, "piglow: leg value out of range\n") ; + exit (EXIT_FAILURE) ; + } + ring = atoi (argv [3]) ; + if ((ring < 0) || (ring > 5)) + { + fprintf (stderr, "piglow: ring value out of range\n") ; + exit (EXIT_FAILURE) ; + } + percent = getPercent (argv [4]) ; + piGlow1 (leg, ring, percent) ; + return 0 ; + } + + failUsage () ; + return 0 ; +} + + diff --git a/examples/blink12drcs.c b/examples/blink12drcs.c new file mode 100644 index 0000000..6ee11fd --- /dev/null +++ b/examples/blink12drcs.c @@ -0,0 +1,125 @@ +/* + * blink12drcs.c: + * Simple sequence over the first 12 GPIO pins - LEDs + * Aimed at the Gertboard, but it's fairly generic. + * This version uses DRC totalk to the ATmega on the Gertboard + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#define GERT_BASE 100 + +static int pinMap [] = +{ + 0, 1, 2, 3, // Pi Native + GERT_BASE + 2, GERT_BASE + 3, GERT_BASE + 4, GERT_BASE + 5, + GERT_BASE + 6, GERT_BASE + 7, GERT_BASE + 8, GERT_BASE + 9, +} ; + +// Simple sequencer data +// Triplets of LED, On/Off and delay + + +int data [] = +{ + 0, 1, 1, + 1, 1, 1, + 0, 0, 0, 2, 1, 1, + 1, 0, 0, 3, 1, 1, + 2, 0, 0, 4, 1, 1, + 3, 0, 0, 5, 1, 1, + 4, 0, 0, 6, 1, 1, + 5, 0, 0, 7, 1, 1, + 6, 0, 0, 8, 1, 1, + 7, 0, 0, 9, 1, 1, + 8, 0, 0, 10, 1, 1, + 9, 0, 0, 11, 1, 1, + 10, 0, 1, + 11, 0, 1, + + 0, 0, 1, // Extra delay + +// Back again + + 11, 1, 1, + 10, 1, 1, + 11, 0, 0, 9, 1, 1, + 10, 0, 0, 8, 1, 1, + 9, 0, 0, 7, 1, 1, + 8, 0, 0, 6, 1, 1, + 7, 0, 0, 5, 1, 1, + 6, 0, 0, 4, 1, 1, + 5, 0, 0, 3, 1, 1, + 4, 0, 0, 2, 1, 1, + 3, 0, 0, 1, 1, 1, + 2, 0, 0, 0, 1, 1, + 1, 0, 1, + 0, 0, 1, + + 0, 0, 1, // Extra delay + + 0, 9, 0, // End marker + +} ; + + +int main (void) +{ + int pin ; + int dataPtr ; + int l, s, d ; + + printf ("Raspberry Pi - 12-LED Sequence\n") ; + printf ("==============================\n") ; + printf ("\n") ; + printf ("Connect LEDs up to the first 4 Pi pins and 8 pins on the ATmega\n") ; + printf (" from PD2 through PB1 in that order,\n") ; + printf (" then sit back and watch the show!\n") ; + + wiringPiSetup () ; + drcSetupSerial (GERT_BASE, 20, "/dev/ttyAMA0", 115200) ; + + for (pin = 0 ; pin < 12 ; ++pin) + pinMode (pinMap [pin], OUTPUT) ; + + dataPtr = 0 ; + + for (;;) + { + l = data [dataPtr++] ; // LED + s = data [dataPtr++] ; // State + d = data [dataPtr++] ; // Duration (10ths) + + if (s == 9) // 9 -> End Marker + { + dataPtr = 0 ; + continue ; + } + + digitalWrite (pinMap [l], s) ; + delay (d * analogRead (GERT_BASE) / 4) ; + } + + return 0 ; +} diff --git a/examples/blink6drcs.c b/examples/blink6drcs.c new file mode 100644 index 0000000..32f4921 --- /dev/null +++ b/examples/blink6drcs.c @@ -0,0 +1,115 @@ +/* + * blink6drcs.c: + * Simple sequence over 6 pins on a remote DRC board. + * Aimed at the Gertduino, but it's fairly generic. + * This version uses DRC to talk to the ATmega on the Gertduino + * + * Copyright (c) 2012-2014 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#define GERT_BASE 100 + +static int pinMap [] = +{ + GERT_BASE + 6, GERT_BASE + 5, GERT_BASE + 3, GERT_BASE + 10, GERT_BASE + 9, GERT_BASE + 13, +} ; + +// Simple sequencer data +// Triplets of LED, On/Off and delay + + +int data [] = +{ + 0, 1, 1, + 1, 1, 1, + 0, 0, 0, 2, 1, 1, + 1, 0, 0, 3, 1, 1, + 2, 0, 0, 4, 1, 1, + 3, 0, 0, 5, 1, 1, + 4, 0, 1, + 5, 0, 1, + + 0, 0, 1, // Extra delay + +// Back again + + 5, 1, 1, + 4, 1, 1, + 5, 0, 0, 3, 1, 1, + 4, 0, 0, 2, 1, 1, + 3, 0, 0, 1, 1, 1, + 2, 0, 0, 0, 1, 1, + 1, 0, 1, + 0, 0, 1, + + 0, 0, 1, // Extra delay + + 0, 9, 0, // End marker + +} ; + + +int main (void) +{ + int pin ; + int dataPtr ; + int l, s, d ; + + printf ("Raspberry Pi - 6-LED Sequence\n") ; + printf ("=============================\n") ; + printf ("\n") ; + printf (" Use the 2 buttons to temporarily speed up the sequence\n") ; + + wiringPiSetupSys () ; // Not using the Pi's GPIO here + drcSetupSerial (GERT_BASE, 20, "/dev/ttyAMA0", 115200) ; + + for (pin = 0 ; pin < 6 ; ++pin) + pinMode (pinMap [pin], OUTPUT) ; + + pinMode (GERT_BASE + 16, INPUT) ; // Buttons + pinMode (GERT_BASE + 17, INPUT) ; + + pullUpDnControl (GERT_BASE + 16, PUD_UP) ; + pullUpDnControl (GERT_BASE + 17, PUD_UP) ; + + dataPtr = 0 ; + + for (;;) + { + l = data [dataPtr++] ; // LED + s = data [dataPtr++] ; // State + d = data [dataPtr++] ; // Duration (10ths) + + if (s == 9) // 9 -> End Marker + { + dataPtr = 0 ; + continue ; + } + + digitalWrite (pinMap [l], s) ; + delay (d * digitalRead (GERT_BASE + 16) * 15 + digitalRead (GERT_BASE + 17) * 20) ; + } + + return 0 ; +} diff --git a/examples/blink8-drcn.c b/examples/blink8-drcn.c new file mode 100644 index 0000000..96c775b --- /dev/null +++ b/examples/blink8-drcn.c @@ -0,0 +1,61 @@ +/* + * blink8-drcn.c: + * Simple sequence over the first 8 GPIO pins - LEDs + * Aimed at the Ladder board, but it's fairly generic. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +int main (void) +{ + int i, led ; + + printf ("Raspberry Pi - 8-LED Sequencer\n") ; + printf ("==============================\n") ; + printf ("\n") ; + printf ("Connect LEDs to the first 8 GPIO pins and watch ...\n") ; + + int pinBase = 100 ; + +// wiringPiSetup () ; + drcSetupNet (pinBase, 100, "192.168.254.21", "6124", "123456") ; + + for (i = 0 ; i < 8 ; ++i) + pinMode (i + pinBase, OUTPUT) ; + + for (;;) + { + for (led = 0 ; led < 8 ; ++led) + { + digitalWrite (led + pinBase, 1) ; + delay (10) ; + } + + for (led = 0 ; led < 8 ; ++led) + { + digitalWrite (led + pinBase, 0) ; + delay (10) ; + } + } +} diff --git a/examples/ds1302.c b/examples/ds1302.c new file mode 100644 index 0000000..f1e9e20 --- /dev/null +++ b/examples/ds1302.c @@ -0,0 +1,238 @@ +/* + * ds1302.c: + * Real Time clock + * + * Copyright (c) 2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include + +#include +#include + +// Register defines + +#define RTC_SECS 0 +#define RTC_MINS 1 +#define RTC_HOURS 2 +#define RTC_DATE 3 +#define RTC_MONTH 4 +#define RTC_DAY 5 +#define RTC_YEAR 6 +#define RTC_WP 7 +#define RTC_TC 8 +#define RTC_BM 31 + + +static unsigned int masks [] = { 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x07, 0xFF } ; + + +/* + * bcdToD: dToBCD: + * BCD decode/encode + ********************************************************************************* + */ + +static int bcdToD (unsigned int byte, unsigned int mask) +{ + unsigned int b1, b2 ; + byte &= mask ; + b1 = byte & 0x0F ; + b2 = ((byte >> 4) & 0x0F) * 10 ; + return b1 + b2 ; +} + +static unsigned int dToBcd (unsigned int byte) +{ + return ((byte / 10) << 4) + (byte % 10) ; +} + + +/* + * ramTest: + * Simple test of the 31 bytes of RAM inside the DS1302 chip + ********************************************************************************* + */ + +static int ramTestValues [] = + { 0x00, 0xFF, 0xAA, 0x55, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0xF0, 0x0F, -1 } ; + +static int ramTest (void) +{ + int addr ; + int got ; + int i = 0 ; + int errors = 0 ; + int testVal ; + + printf ("DS1302 RAM TEST\n") ; + + testVal = ramTestValues [i] ; + + while (testVal != -1) + { + for (addr = 0 ; addr < 31 ; ++addr) + ds1302ramWrite (addr, testVal) ; + + for (addr = 0 ; addr < 31 ; ++addr) + if ((got = ds1302ramRead (addr)) != testVal) + { + printf ("DS1302 RAM Failure: Address: %2d, Expected: 0x%02X, Got: 0x%02X\n", + addr, testVal, got) ; + ++errors ; + } + testVal = ramTestValues [++i] ; + } + + for (addr = 0 ; addr < 31 ; ++addr) + ds1302ramWrite (addr, addr) ; + + for (addr = 0 ; addr < 31 ; ++addr) + if ((got = ds1302ramRead (addr)) != addr) + { + printf ("DS1302 RAM Failure: Address: %2d, Expected: 0x%02X, Got: 0x%02X\n", + addr, addr, got) ; + ++errors ; + } + + if (errors == 0) + printf ("-- DS1302 RAM TEST: OK\n") ; + else + printf ("-- DS1302 RAM TEST FAILURE. %d errors.\n", errors) ; + + return 0 ; +} + +/* + * setLinuxClock: + * Set the Linux clock from the hardware + ********************************************************************************* + */ + +static int setLinuxClock (void) +{ + char dateTime [20] ; + char command [64] ; + int clock [8] ; + + + printf ("Setting the Linux Clock from the DS1302... ") ; fflush (stdout) ; + + ds1302clockRead (clock) ; + +// [MMDDhhmm[[CC]YY][.ss]] + + sprintf (dateTime, "%02d%02d%02d%02d%02d%02d.%02d", + bcdToD (clock [RTC_MONTH], masks [RTC_MONTH]), + bcdToD (clock [RTC_DATE], masks [RTC_DATE]), + bcdToD (clock [RTC_HOURS], masks [RTC_HOURS]), + bcdToD (clock [RTC_MINS], masks [RTC_MINS]), + 20, + bcdToD (clock [RTC_YEAR], masks [RTC_YEAR]), + bcdToD (clock [RTC_SECS], masks [RTC_SECS])) ; + + sprintf (command, "/bin/date %s", dateTime) ; + system (command) ; + + return 0 ; +} + + +/* + * setDSclock: + * Set the DS1302 block from Linux time + ********************************************************************************* + */ + +static int setDSclock (void) +{ + struct tm t ; + time_t now ; + int clock [8] ; + + printf ("Setting the clock in the DS1302 from Linux time... ") ; + + now = time (NULL) ; + gmtime_r (&now, &t) ; + + clock [ 0] = dToBcd (t.tm_sec) ; // seconds + clock [ 1] = dToBcd (t.tm_min) ; // mins + clock [ 2] = dToBcd (t.tm_hour) ; // hours + clock [ 3] = dToBcd (t.tm_mday) ; // date + clock [ 4] = dToBcd (t.tm_mon + 1) ; // months 0-11 --> 1-12 + clock [ 5] = dToBcd (t.tm_wday + 1) ; // weekdays (sun 0) + clock [ 6] = dToBcd (t.tm_year - 100) ; // years + clock [ 7] = 0 ; // W-Protect off + + ds1302clockWrite (clock) ; + + printf ("OK\n") ; + + return 0 ; +} + + + + +int main (int argc, char *argv []) +{ + int i ; + int clock [8] ; + + wiringPiSetup () ; + ds1302setup (0, 1, 2) ; + + if (argc == 2) + { + /**/ if (strcmp (argv [1], "-slc") == 0) + return setLinuxClock () ; + else if (strcmp (argv [1], "-sdsc") == 0) + return setDSclock () ; + else if (strcmp (argv [1], "-rtest") == 0) + return ramTest () ; + else + { + printf ("Usage: ds1302 [-slc | -sdsc | -rtest]\n") ; + return EXIT_FAILURE ; + } + } + + for (i = 0 ;; ++i) + { + printf ("%5d: ", i) ; + + ds1302clockRead (clock) ; + printf (" %2d:%02d:%02d", + bcdToD (clock [2], masks [2]), bcdToD (clock [1], masks [1]), bcdToD (clock [0], masks [0])) ; + + printf (" %2d/%02d/%04d", + bcdToD (clock [3], masks [3]), bcdToD (clock [4], masks [4]), bcdToD (clock [6], masks [6]) + 2000) ; + + printf ("\n") ; + + delay (200) ; + } + + return 0 ; +} diff --git a/examples/lcd-adafruit.c b/examples/lcd-adafruit.c new file mode 100644 index 0000000..47c9b9b --- /dev/null +++ b/examples/lcd-adafruit.c @@ -0,0 +1,347 @@ +/* + * lcd-adafruit.c: + * Text-based LCD driver test code + * This is designed to drive the Adafruit RGB LCD Plate + * with the additional 5 buttons for the Raspberry Pi + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef TRUE +# define TRUE (1==1) +# define FALSE (1==2) +#endif + + +// Defines for the Adafruit Pi LCD interface board + +#define AF_BASE 100 +#define AF_RED (AF_BASE + 6) +#define AF_GREEN (AF_BASE + 7) +#define AF_BLUE (AF_BASE + 8) + +#define AF_E (AF_BASE + 13) +#define AF_RW (AF_BASE + 14) +#define AF_RS (AF_BASE + 15) + +#define AF_DB4 (AF_BASE + 12) +#define AF_DB5 (AF_BASE + 11) +#define AF_DB6 (AF_BASE + 10) +#define AF_DB7 (AF_BASE + 9) + +#define AF_SELECT (AF_BASE + 0) +#define AF_RIGHT (AF_BASE + 1) +#define AF_DOWN (AF_BASE + 2) +#define AF_UP (AF_BASE + 3) +#define AF_LEFT (AF_BASE + 4) + + +// User-Defined character test + +static unsigned char newChar [8] = +{ + 0b00100, + 0b00100, + 0b00000, + 0b00100, + 0b01110, + 0b11011, + 0b11011, + 0b10001, +} ; + +// Global lcd handle: + +static int lcdHandle ; + +/* + * usage: + ********************************************************************************* + */ + +int usage (const char *progName) +{ + fprintf (stderr, "Usage: %s colour\n", progName) ; + return EXIT_FAILURE ; +} + + +/* + * scrollMessage: + ********************************************************************************* + */ + +static const char *message = + " " + "Wiring Pi by Gordon Henderson. HTTP://WIRINGPI.COM/" + " " ; + +void scrollMessage (int line, int width) +{ + char buf [32] ; + static int position = 0 ; + static int timer = 0 ; + + if (millis () < timer) + return ; + + timer = millis () + 200 ; + + strncpy (buf, &message [position], width) ; + buf [width] = 0 ; + lcdPosition (lcdHandle, 0, line) ; + lcdPuts (lcdHandle, buf) ; + + if (++position == (strlen (message) - width)) + position = 0 ; +} + + +/* + * setBacklightColour: + * The colour outputs are inverted. + ********************************************************************************* + */ + +static void setBacklightColour (int colour) +{ + colour &= 7 ; + + digitalWrite (AF_RED, !(colour & 1)) ; + digitalWrite (AF_GREEN, !(colour & 2)) ; + digitalWrite (AF_BLUE, !(colour & 4)) ; +} + + +/* + * adafruitLCDSetup: + * Setup the Adafruit board by making sure the additional pins are + * set to the correct modes, etc. + ********************************************************************************* + */ + +static void adafruitLCDSetup (int colour) +{ + int i ; + +// Backlight LEDs + + pinMode (AF_RED, OUTPUT) ; + pinMode (AF_GREEN, OUTPUT) ; + pinMode (AF_BLUE, OUTPUT) ; + setBacklightColour (colour) ; + +// Input buttons + + for (i = 0 ; i <= 4 ; ++i) + { + pinMode (AF_BASE + i, INPUT) ; + pullUpDnControl (AF_BASE + i, PUD_UP) ; // Enable pull-ups, switches close to 0v + } + +// Control signals + + pinMode (AF_RW, OUTPUT) ; digitalWrite (AF_RW, LOW) ; // Not used with wiringPi - always in write mode + +// The other control pins are initialised with lcdInit () + + lcdHandle = lcdInit (2, 16, 4, AF_RS, AF_E, AF_DB4,AF_DB5,AF_DB6,AF_DB7, 0,0,0,0) ; + + if (lcdHandle < 0) + { + fprintf (stderr, "lcdInit failed\n") ; + exit (EXIT_FAILURE) ; + } +} + + +/* + * waitForEnter: + * On the Adafruit display, wait for the select button + ********************************************************************************* + */ + +static void waitForEnter (void) +{ + printf ("Press SELECT to continue: ") ; fflush (stdout) ; + + while (digitalRead (AF_SELECT) == HIGH) // Wait for push + delay (1) ; + + while (digitalRead (AF_SELECT) == LOW) // Wait for release + delay (1) ; + + printf ("OK\n") ; +} + + +/* + * speedTest: + * Test the update speed of the display + ********************************************************************************* + */ + +static void speedTest (void) +{ + unsigned int start, end, taken ; + int times ; + + lcdClear (lcdHandle) ; + start = millis () ; + for (times = 0 ; times < 10 ; ++times) + { + lcdPuts (lcdHandle, "0123456789ABCDEF") ; + lcdPuts (lcdHandle, "0123456789ABCDEF") ; + } + end = millis () ; + taken = (end - start) / 10; + + lcdClear (lcdHandle) ; + lcdPosition (lcdHandle, 0, 0) ; lcdPrintf (lcdHandle, "Speed: %dmS", taken) ; + lcdPosition (lcdHandle, 0, 1) ; lcdPrintf (lcdHandle, "For full update") ; + + waitForEnter () ; + + lcdClear (lcdHandle) ; + lcdPosition (lcdHandle, 0, 0) ; lcdPrintf (lcdHandle, "Time: %dmS", taken / 32) ; + lcdPosition (lcdHandle, 0, 1) ; lcdPrintf (lcdHandle, "Per character") ; + + waitForEnter () ; + + lcdClear (lcdHandle) ; + lcdPosition (lcdHandle, 0, 0) ; lcdPrintf (lcdHandle, "%d cps...", 32000 / taken) ; + + waitForEnter () ; +} + + +/* + * The works + ********************************************************************************* + */ + +int main (int argc, char *argv[]) +{ + int colour ; + int cols = 16 ; + int waitForRelease = FALSE ; + + struct tm *t ; + time_t tim ; + + char buf [32] ; + + if (argc != 2) + return usage (argv [0]) ; + + printf ("Raspberry Pi Adafruit LCD test\n") ; + printf ("==============================\n") ; + + colour = atoi (argv [1]) ; + + wiringPiSetupSys () ; + mcp23017Setup (AF_BASE, 0x20) ; + + adafruitLCDSetup (colour) ; + + lcdPosition (lcdHandle, 0, 0) ; lcdPuts (lcdHandle, "Gordon Henderson") ; + lcdPosition (lcdHandle, 0, 1) ; lcdPuts (lcdHandle, " wiringpi.com ") ; + + waitForEnter () ; + + lcdPosition (lcdHandle, 0, 1) ; lcdPuts (lcdHandle, "Adafruit RGB LCD") ; + + waitForEnter () ; + + lcdCharDef (lcdHandle, 2, newChar) ; + + lcdClear (lcdHandle) ; + lcdPosition (lcdHandle, 0, 0) ; + lcdPuts (lcdHandle, "User Char: ") ; + lcdPutchar (lcdHandle, 2) ; + + lcdCursor (lcdHandle, TRUE) ; + lcdCursorBlink (lcdHandle, TRUE) ; + + waitForEnter () ; + + lcdCursor (lcdHandle, FALSE) ; + lcdCursorBlink (lcdHandle, FALSE) ; + + speedTest () ; + + lcdClear (lcdHandle) ; + + for (;;) + { + scrollMessage (0, cols) ; + + tim = time (NULL) ; + t = localtime (&tim) ; + + sprintf (buf, "%02d:%02d:%02d", t->tm_hour, t->tm_min, t->tm_sec) ; + + lcdPosition (lcdHandle, (cols - 8) / 2, 1) ; + lcdPuts (lcdHandle, buf) ; + +// Check buttons to cycle colour + +// If Up or Down are still pushed, then skip + + if (waitForRelease) + { + if ((digitalRead (AF_UP) == LOW) || (digitalRead (AF_DOWN) == LOW)) + continue ; + else + waitForRelease = FALSE ; + } + + if (digitalRead (AF_UP) == LOW) // Pushed + { + colour = colour + 1 ; + if (colour == 8) + colour = 0 ; + setBacklightColour (colour) ; + waitForRelease = TRUE ; + } + + if (digitalRead (AF_DOWN) == LOW) // Pushed + { + colour = colour - 1 ; + if (colour == -1) + colour = 7 ; + setBacklightColour (colour) ; + waitForRelease = TRUE ; + } + + } + + return 0 ; +} diff --git a/examples/max31855.c b/examples/max31855.c new file mode 100644 index 0000000..36b3cf6 --- /dev/null +++ b/examples/max31855.c @@ -0,0 +1,60 @@ +/* + * max31855.c: + * SPI Thermocouple interface chip + * + * Copyright (c) 2015 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include + +#include +#include + +int main (int argc, char *argv []) +{ + int i = 0 ; + + wiringPiSetup () ; + max31855Setup (200, 0) ; + max31855Setup (400, 1) ; + + for (;;) + { + if (i == 0) + { + printf ("+------+------+------+------++------+------+------+------+\n") ; + printf ("| Raw | Err | C | F || Raw | Err | C | F |\n") ; + printf ("+------+------+------+------++------+------+------+------+\n") ; + } + + printf ("| %4d | %4d | %4d | %4d |", analogRead (200), analogRead (201), analogRead (202), analogRead (203)) ; + printf ("| %4d | %4d | %4d | %4d |\n", analogRead (400), analogRead (401), analogRead (402), analogRead (403)) ; + delay (500) ; + + if (++i == 10) + i = 0 ; + + } + +} diff --git a/examples/nes.c b/examples/nes.c new file mode 100644 index 0000000..31908e8 --- /dev/null +++ b/examples/nes.c @@ -0,0 +1,67 @@ +/* + * nes.c: + * Test program for an old NES controller connected to the Pi. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#include +#include + +#define BLANK "| " + +int main () +{ + int joystick ; + unsigned int buttons ; + + if (wiringPiSetup () == -1) + { + fprintf (stdout, "oops: %s\n", strerror (errno)) ; + return 1 ; + } + + if ((joystick = setupNesJoystick (2, 1, 0)) == -1) + { + fprintf (stdout, "Unable to setup joystick\n") ; + return 1 ; + } + + for (;;) + { + buttons = readNesJoystick (joystick) ; + + if ((buttons & NES_UP) != 0) printf ("| UP " ) ; else printf (BLANK) ; + if ((buttons & NES_DOWN) != 0) printf ("| DOWN " ) ; else printf (BLANK) ; + if ((buttons & NES_LEFT) != 0) printf ("| LEFT " ) ; else printf (BLANK) ; + if ((buttons & NES_RIGHT) != 0) printf ("|RIGHT " ) ; else printf (BLANK) ; + if ((buttons & NES_SELECT) != 0) printf ("|SELECT" ) ; else printf (BLANK) ; + if ((buttons & NES_START) != 0) printf ("|START " ) ; else printf (BLANK) ; + if ((buttons & NES_A) != 0) printf ("| A " ) ; else printf (BLANK) ; + if ((buttons & NES_B) != 0) printf ("| B " ) ; else printf (BLANK) ; + printf ("|\n") ; + } + + return 0 ; +} diff --git a/examples/q2w/Makefile b/examples/q2w/Makefile new file mode 100644 index 0000000..8f773bf --- /dev/null +++ b/examples/q2w/Makefile @@ -0,0 +1,84 @@ +# +# Makefile: +# wiringPi - A "wiring" library for the Raspberry Pi +# https://projects.drogon.net/wiring-pi +# +# Copyright (c) 2012-2013 Gordon Henderson +################################################################################# +# This file is part of wiringPi: +# A "wiring" library for the Raspberry Pi +# +# wiringPi is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# wiringPi is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with wiringPi. If not, see . +################################################################################# + +ifneq ($V,1) +Q ?= @ +endif + +#DEBUG = -g -O0 +DEBUG = -O3 +CC = gcc +INCLUDE = -I/usr/local/include +CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe + +LDFLAGS = -L/usr/local/lib +LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm + +############################################################################### + +SRC = blink.c button.c blink-io.c volts.c bright.c + +OBJ = $(SRC:.c=.o) + +BINS = $(SRC:.c=) + +all: $(BINS) + +blink: blink.o + $Q echo [link] + $Q $(CC) -o $@ blink.o $(LDFLAGS) $(LDLIBS) + +blink-io: blink-io.o + $Q echo [link] + $Q $(CC) -o $@ blink-io.o $(LDFLAGS) $(LDLIBS) + +button: button.o + $Q echo [link] + $Q $(CC) -o $@ button.o $(LDFLAGS) $(LDLIBS) + +volts: volts.o + $Q echo [link] + $Q $(CC) -o $@ volts.o $(LDFLAGS) $(LDLIBS) + +bright: bright.o + $Q echo [link] + $Q $(CC) -o $@ bright.o $(LDFLAGS) $(LDLIBS) + + +.c.o: + $Q echo [CC] $< + $Q $(CC) -c $(CFLAGS) $< -o $@ + +clean: + $Q echo "[Clean]" + $Q rm -f $(OBJ) *~ core tags $(BINS) + +tags: $(SRC) + $Q echo [ctags] + $Q ctags $(SRC) + +depend: + makedepend -Y $(SRC) + +# DO NOT DELETE diff --git a/examples/q2w/binary.c b/examples/q2w/binary.c new file mode 100644 index 0000000..3c987c6 --- /dev/null +++ b/examples/q2w/binary.c @@ -0,0 +1,79 @@ +/* + * binary.c: + * Using the Quick 2 wire 16-bit GPIO expansion board to output + * a binary counter. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#define Q2W_BASE 100 + +int main (void) +{ + int i, bit ; + +// Enable the on-goard GPIO + + wiringPiSetup () ; + +// Add in the mcp23017 on the q2w board + + mcp23017Setup (Q2W_BASE, 0x20) ; + + printf ("Raspberry Pi - quite2Wire MCP23017 Test\n") ; + +// On-board button Input: + + pinMode (0, INPUT) ; + +// First 10 pins on q2w board as outputs: + + for (i = 0 ; i < 10 ; ++i) + pinMode (Q2W_BASE + i, OUTPUT) ; + +// Last pin as an input with the internal pull-up enabled + + pinMode (Q2W_BASE + 15, INPUT) ; + pullUpDnControl (Q2W_BASE + 15, PUD_UP) ; + +// Loop, outputting a binary number, +// Go faster with the button, or stop if the +// on-board button is pushed + + for (;;) + { + for (i = 0 ; i < 1024 ; ++i) + { + for (bit = 0 ; bit < 10 ; ++bit) + digitalWrite (Q2W_BASE + bit, i & (1 << bit)) ; + + while (digitalRead (0) == HIGH) // While pushed + delay (1) ; + + if (digitalRead (Q2W_BASE + 15) == HIGH) // Not Pushed + delay (100) ; + } + } + return 0 ; +} diff --git a/examples/q2w/blink-io.c b/examples/q2w/blink-io.c new file mode 100644 index 0000000..4dd4276 --- /dev/null +++ b/examples/q2w/blink-io.c @@ -0,0 +1,61 @@ +/* + * blink-io.c: + * Simple "blink" test for the Quick2Wire 16-pin IO board. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#define LED 1 +#define Q2W_BASE 100 + +int main (void) +{ + +// Enable the on-goard GPIO + + wiringPiSetup () ; + +// Add in the mcp23017 on the q2w board + + mcp23017Setup (Q2W_BASE, 0x20) ; + + printf ("Raspberry Pi - Quick2Wire MCP23017 Blink Test\n") ; + +// Blink the on-board LED as well as one on the mcp23017 + + pinMode (LED, OUTPUT) ; + pinMode (Q2W_BASE + 0, OUTPUT) ; + + for (;;) + { + digitalWrite (LED, HIGH) ; + digitalWrite (Q2W_BASE + 0, HIGH) ; + delay (500) ; + digitalWrite (LED, LOW) ; + digitalWrite (Q2W_BASE + 0, LOW) ; + delay (500) ; + } + + return 0 ; +} diff --git a/examples/q2w/blink.c b/examples/q2w/blink.c new file mode 100644 index 0000000..62b694a --- /dev/null +++ b/examples/q2w/blink.c @@ -0,0 +1,50 @@ +/* + * blink.c: + * Simple "blink" test for the Quick2Wire interface board. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include + +#define LED 1 + +int main (void) +{ + +// Enable the on-goard GPIO + + wiringPiSetup () ; + + printf ("Raspberry Pi - Quick2Wire Mainboard LED Blink Test\n") ; + + pinMode (LED, OUTPUT) ; + + for (;;) + { + digitalWrite (LED, HIGH) ; + delay (500) ; + digitalWrite (LED, LOW) ; + delay (500) ; + } + + return 0 ; +} diff --git a/examples/q2w/blink.sh b/examples/q2w/blink.sh new file mode 100644 index 0000000..bb6107a --- /dev/null +++ b/examples/q2w/blink.sh @@ -0,0 +1,37 @@ +#!/bin/sh -e +# +# blink.sh: +# Standard "blink" program in wiringPi. Blinks an LED connected +# to the LED on the Quick2Wire board +# +# Copyright (c) 2012-2013 Gordon Henderson. +####################################################################### +# This file is part of wiringPi: +# https://projects.drogon.net/raspberry-pi/wiringpi/ +# +# wiringPi is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# wiringPi is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with wiringPi. If not, see . +####################################################################### + +# LED Pin - wiringPi pin 1 is BCM_GPIO 18. + +LED=1 + +gpio mode $LED out + +while true; do + gpio write $LED 1 + sleep 0.5 + gpio write $LED 0 + sleep 0.5 +done diff --git a/examples/q2w/bright.c b/examples/q2w/bright.c new file mode 100644 index 0000000..2318834 --- /dev/null +++ b/examples/q2w/bright.c @@ -0,0 +1,59 @@ +/* + * bright.c: + * Vary the Q2W LED brightness with the analog card + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#define LED 1 +#define Q2W_ABASE 120 + +int main (void) +{ + int value ; + +// Enable the on-goard GPIO + + wiringPiSetup () ; + +// Add in the pcf8591 on the q2w board + + pcf8591Setup (Q2W_ABASE, 0x48) ; + + printf ("Raspberry Pi - Quick2Wire Analog Test\n") ; + +// Setup the LED + + pinMode (LED, PWM_OUTPUT) ; + pwmWrite (LED, 0) ; + + for (;;) + { + value = analogRead (Q2W_ABASE + 0) ; + pwmWrite (LED, value * 4) ; + delay (10) ; + } + + return 0 ; +} diff --git a/examples/q2w/button.c b/examples/q2w/button.c new file mode 100644 index 0000000..1781f02 --- /dev/null +++ b/examples/q2w/button.c @@ -0,0 +1,63 @@ +/* + * button.c: + * Simple button test for the Quick2Wire interface board. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include + +#define BUTTON 0 +#define LED1 1 +#define LED2 7 + +int main (void) +{ + +// Enable the on-goard GPIO + + wiringPiSetup () ; + + printf ("Raspberry Pi - Quick2Wire Mainboard Button & LED Test\n") ; + + pinMode (BUTTON, INPUT) ; + pinMode (LED1, OUTPUT) ; + pinMode (LED2, OUTPUT) ; + + digitalWrite (LED1, HIGH) ; // On-board LED on + digitalWrite (LED2, LOW) ; // 2nd LED off + + for (;;) + { + if (digitalRead (BUTTON) == HIGH) // Swap LED states + { + digitalWrite (LED1, LOW) ; + digitalWrite (LED2, HIGH) ; + while (digitalRead (BUTTON) == HIGH) + delay (1) ; + digitalWrite (LED1, HIGH) ; + digitalWrite (LED2, LOW) ; + } + delay (1) ; + } + + return 0 ; +} diff --git a/examples/q2w/volts.c b/examples/q2w/volts.c new file mode 100644 index 0000000..e091093 --- /dev/null +++ b/examples/q2w/volts.c @@ -0,0 +1,62 @@ +/* + * volts.c: + * Read in all 4 analogs on the Q2W analog board. + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#define LED 1 +#define Q2W_ABASE 120 + +int main (void) +{ + int value, pin ; + +// Enable the on-goard GPIO + + wiringPiSetup () ; + + pinMode (LED, OUTPUT) ; // On-board LED + +// Add in the pcf8591 on the q2w board + + pcf8591Setup (Q2W_ABASE, 0x48) ; + + printf ("Raspberry Pi - Quick2Wire Voltmeter\n") ; + + for (;;) + { + for (pin = 0 ; pin < 4 ; ++pin) + { + value = analogRead (Q2W_ABASE + pin) ; + printf (" %5.2f", (double)value * 3.3 / 255.0) ; + } + printf ("\r") ; fflush (stdout) ; + + delay (100) ; + digitalWrite (LED, !digitalRead (LED)) ; // Flicker the LED + } + + return 0 ; +} diff --git a/examples/rht03.c b/examples/rht03.c new file mode 100644 index 0000000..854f837 --- /dev/null +++ b/examples/rht03.c @@ -0,0 +1,86 @@ +/* + * rht03.c: + * Driver for the MaxDetect series sensors + * + * Copyright (c) 2012-2013 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include + +#include +#include + +#define RHT03_PIN 7 + +/* + *********************************************************************** + * The main program + *********************************************************************** + */ + +int main (void) +{ + int result, temp, rh ; + int minT, maxT, minRH, maxRH ; + + int numGood, numBad ; + + wiringPiSetup () ; + piHiPri (55) ; + + minT = 1000 ; + maxT = -1000 ; + + minRH = 1000 ; + maxRH = -1000 ; + + numGood = numBad = 0 ; + + for (;;) + { + delay (100) ; + + result = readRHT03 (RHT03_PIN, &temp, &rh) ; + + if (!result) + { + printf (".") ; + fflush (stdout) ; + ++numBad ; + continue ; + } + + ++numGood ; + + if (temp < minT) minT = temp ; + if (temp > maxT) maxT = temp ; + if (rh < minRH) minRH = rh ; + if (rh > maxRH) maxRH = rh ; + + printf ("\r%6d, %6d: ", numGood, numBad) ; + printf ("Temp: %5.1f, RH: %5.1f%%", temp / 10.0, rh / 10.0) ; + printf (" Max/Min Temp: %5.1f:%5.1f", maxT / 10.0, minT / 10.0) ; + printf (" Max/Min RH: %5.1f:%5.1f", maxRH / 10.0, minRH / 10.0) ; + + printf ("\n") ; + } + + return 0 ; +} diff --git a/examples/scrollPhat/Makefile b/examples/scrollPhat/Makefile new file mode 100644 index 0000000..2471f69 --- /dev/null +++ b/examples/scrollPhat/Makefile @@ -0,0 +1,79 @@ +# +# Makefile: +# wiringPi - A "wiring" library for the Raspberry Pi +# https://projects.drogon.net/wiring-pi +# +# Copyright (c) 2012-2015 Gordon Henderson +################################################################################# +# This file is part of wiringPi: +# A "wiring" library for the Raspberry Pi +# +# wiringPi is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# wiringPi is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with wiringPi. If not, see . +################################################################################# + +ifneq ($V,1) +Q ?= @ +endif + +#DEBUG = -g -O0 +DEBUG = -O3 +CC = gcc +INCLUDE = -I/usr/local/include +CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe + +LDFLAGS = -L/usr/local/lib +LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm + +# Should not alter anything below this line +############################################################################### + +SRC = scphat.c test.c + +OBJ = $(SRC:.c=.o) + +BINS = $(SRC:.c=) + +all: $(BINS) + +test: test.o + $Q echo [link] + $Q $(CC) -o $@ test.o $(LDFLAGS) $(LDLIBS) + +scphat: scphat.o + $Q echo [link] + $Q $(CC) -o $@ scphat.o $(LDFLAGS) $(LDLIBS) + + +.c.o: + $Q echo [CC] $< + $Q $(CC) -c $(CFLAGS) $< -o $@ + +clean: + $Q echo "[Clean]" + $Q rm -f $(OBJ) *~ core tags $(BINS) + +tags: $(SRC) + $Q echo [ctags] + $Q ctags $(SRC) + +install: scphat + $Q echo Installing scphat into /usr/local/bin + $Q cp -a scphat /usr/local/bin/scphat + $Q chmod 755 /usr/local/bin/scphat + $Q echo Done. Remember to load the I2C drivers if needed. + +depend: + makedepend -Y $(SRC) + +# DO NOT DELETE diff --git a/examples/scrollPhat/scphat.c b/examples/scrollPhat/scphat.c new file mode 100644 index 0000000..8f90bad --- /dev/null +++ b/examples/scrollPhat/scphat.c @@ -0,0 +1,230 @@ +/* + * scphat.c: + * Little program to allow use of the Pimoroni Sctoll Phat + * from the command-line. + * + * Copyright (c) 2015-2016 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include + +#include +#include + +static char *progName ; + + +/* + * checkArgs: + * Count the arguments for each little function + ********************************************************************************* + */ + +static void checkArgs (char *command, int num, int arg, int argc) +{ + if ((arg + num) < argc) + return ; + + fprintf (stderr, "%s: Not enough data for %s command.\n", progName, command) ; + exit (EXIT_FAILURE) ; +} + + +/* + * doClear: + * Clear the display + ********************************************************************************* + */ + +static int doClear (void) +{ + scrollPhatClear () ; + return 1 ; +} + + +/* + * doBright + ********************************************************************************* + */ + +static int doBright (int arg, int argc, char *argv []) +{ + checkArgs ("bright", 1, arg, argc) ; + scrollPhatIntensity (atoi (argv [arg+1])) ; + return 2 ; +} + + + +/* + * doPlot + ********************************************************************************* + */ + +static int doPlot (int arg, int argc, char *argv []) +{ + checkArgs ("plot", 2, arg, argc) ; + scrollPhatPoint (atoi (argv [arg+1]), atoi (argv [arg+2]), 1) ; + scrollPhatUpdate () ; + return 3 ; +} + + +/* + * doLine + ********************************************************************************* + */ + +static int doLine (int arg, int argc, char *argv []) +{ + checkArgs ("line", 4, arg, argc) ; + scrollPhatLine (atoi (argv [arg+1]), atoi (argv [arg+2]), + atoi (argv [arg+3]), atoi (argv [arg+4]), 1) ; + scrollPhatUpdate () ; + return 5 ; +} + + +/* + * doLineTo + ********************************************************************************* + */ + +static int doLineTo (int arg, int argc, char *argv []) +{ + checkArgs ("lineto", 2, arg, argc) ; + scrollPhatLineTo (atoi (argv [arg+1]), atoi (argv [arg+2]), 1) ; + scrollPhatUpdate () ; + return 3 ; +} + + +/* + * doWait + ********************************************************************************* + */ + +static int doWait (int arg, int argc, char *argv []) +{ + checkArgs ("wait", 1, arg, argc) ; + delay (atoi (argv [arg+1]) * 100) ; + scrollPhatUpdate () ; + return 2 ; +} + + +/* + * doSpeed + ********************************************************************************* + */ + +static int doSpeed (int arg, int argc, char *argv []) +{ + checkArgs ("speed", 1, arg, argc) ; + scrollPhatPrintSpeed (atoi (argv [arg+1])) ; + return 2 ; +} + + +/* + * doScroll + ********************************************************************************* + */ + +static int doScroll (int arg, int argc, char *argv []) +{ + checkArgs ("scroll", 1, arg, argc) ; + scrollPhatPuts (argv [arg+1]) ; + return 2 ; +} + + +static void failUsage (void) +{ + fprintf (stderr, "Usage: %s command [paremters] ...\n", progName) ; + fprintf (stderr, " commands:\n") ; + fprintf (stderr, " clear/cls - Clear the display\n") ; + fprintf (stderr, " bright N - Set display brightness; 1-100\n") ; + fprintf (stderr, " plot X Y - Set a single pixel at location X Y; 0-10, 0-4\n") ; + fprintf (stderr, " line X1 Y1 X2 Y2 - Draw a line from the 2 points\n") ; + fprintf (stderr, " lineto X2 Y2 - Draw a line from the last point to the new one\n") ; + fprintf (stderr, " wait/delay N - Wait for N 10ths seconds\n") ; + fprintf (stderr, " speed N - Set scrolling speed (cps)\n") ; + fprintf (stderr, " scroll S - Scroll the given string\n") ; + fprintf (stderr, "\n") ; + fprintf (stderr, " Example: %s plot 0 0 wait 50 scroll \" Hello \"\n", progName) ; + exit (EXIT_FAILURE) ; +} + + +/* + * the works + ********************************************************************************* + */ + +int main (int argc, char *argv []) +{ + int arg = 1 ; + char *command ; + + progName = argv [0] ; + + wiringPiSetupSys () ; + + if (scrollPhatSetup () != 0) + { + fprintf (stderr, "%s: Unable to initialise the scrollPhat: %s\n", progName, strerror (errno)) ; + exit (EXIT_FAILURE) ; + } + + progName = argv [0] ; + + if (argc < 2) + { + fprintf (stderr, "%s: Nothing to do...\n", argv [0]) ; + failUsage () ; + } + + while (arg != argc) + { + command = argv [arg] ; + /**/ if (strcasecmp (command, "clear") == 0) arg += doClear () ; + else if (strcasecmp (command, "cls") == 0) arg += doClear () ; + else if (strcasecmp (command, "bright") == 0) arg += doBright (arg, argc, argv) ; + else if (strcasecmp (command, "plot") == 0) arg += doPlot (arg, argc, argv) ; + else if (strcasecmp (command, "line") == 0) arg += doLine (arg, argc, argv) ; + else if (strcasecmp (command, "lineto") == 0) arg += doLineTo (arg, argc, argv) ; + else if (strcasecmp (command, "wait") == 0) arg += doWait (arg, argc, argv) ; + else if (strcasecmp (command, "delay") == 0) arg += doWait (arg, argc, argv) ; + else if (strcasecmp (command, "speed") == 0) arg += doSpeed (arg, argc, argv) ; + else if (strcasecmp (command, "scroll") == 0) arg += doScroll (arg, argc, argv) ; + else + { + fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [arg]) ; + failUsage () ; + } + } + + return 0 ; +} diff --git a/examples/scrollPhat/test.c b/examples/scrollPhat/test.c new file mode 100644 index 0000000..e4d8021 --- /dev/null +++ b/examples/scrollPhat/test.c @@ -0,0 +1,115 @@ +/* + * test.c: + * Little test program forthe Pimoroni Scroll Phat. + * + * Copyright (c) 2015-2016 Gordon Henderson. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include + +#include + + +/* + * prompt: + * Simple prompt & wait + ********************************************************************************* + */ + +static void prompt (const char *p) +{ + printf (" %s. Press ENTER: ", p) ; + (void)getchar () ; +} + + +/* + * the works + ********************************************************************************* + */ + +int main (void) +{ + int x, y ; + + printf ("\n") ; + printf ("Scroll Phat Test program\n") ; + printf ("========================\n") ; + + if (scrollPhatSetup () != 0) + { + printf ("Unable to initialise the scrollPhat: %s\n", strerror (errno)) ; + exit (1) ; + } + + printf ("-> Scroll Phat initialised OK\n") ; + printf ("... Basic display tests.\n\n") ; + + prompt ("Display ought to be blank") ; + +// Light all pixels using one point at a time + + for (y = 0 ; y < 5 ; ++y) + for (x = 0 ; x < 12 ; ++x) + scrollPhatPoint (x, y, 1) ; + scrollPhatUpdate () ; + + prompt ("Display ought to be all lit-up") ; + +// Big rectangle + + scrollPhatClear () ; + scrollPhatRectangle (0,0, 10, 4, 1, 0) ; + scrollPhatUpdate () ; + + prompt ("There should now be a rectangle round the outside") ; + + scrollPhatLine (0,0, 10,4, 1) ; + scrollPhatLine (0,4, 10,0, 1) ; + scrollPhatUpdate () ; + + prompt ("Diagonal lines") ; + + scrollPhatIntensity (1) ; + + prompt ("Minimum brightness") ; + + scrollPhatIntensity (100) ; + + prompt ("Maximum brightness") ; + + scrollPhatIntensity (10) ; + + prompt ("Default brightness") ; + + scrollPhatClear () ; + + printf (" Message Test...Press Ctrl-C to exit: ") ; + fflush (stdout) ; + + scrollPhatPrintSpeed (75) ; + for (;;) + scrollPhatPuts (" Welcome to the scroll phat from Pimoroni ") ; + + return 0 ; +} diff --git a/gpio/readall.c b/gpio/readall.c index 1279f01..462a22f 100644 --- a/gpio/readall.c +++ b/gpio/readall.c @@ -42,6 +42,28 @@ extern int wpMode ; # define FALSE (1==2) #endif +/*----------------------------------------------------------------------------*/ +/* + * doReadallExternal: + * A relatively crude way to read the pins on an external device. + * We don't know the input/output mode of pins, but we can tell + * if it's an analog pin or a digital one... + */ +/*----------------------------------------------------------------------------*/ +static void doReadallExternal (void) +{ + int pin ; + + printf ("+------+---------+--------+\n") ; + printf ("| Pin | Digital | Analog |\n") ; + printf ("+------+---------+--------+\n") ; + + for (pin = wiringPiNodes->pinBase ; pin <= wiringPiNodes->pinMax ; ++pin) + printf ("| %4d | %4d | %4d |\n", pin, digitalRead (pin), analogRead (pin)) ; + + printf ("+------+---------+--------+\n") ; +} + /*----------------------------------------------------------------------------*/ static const char *alts [] = { @@ -694,6 +716,12 @@ void doReadall(int argc, char *argv[]) { int model, rev, mem, maker, overVolted, isAll; char *headerName, *physNames; + // External readall + if (wiringPiNodes != NULL) { + doReadallExternal(); + return; + } + if (argc <= 2) { isAll = FALSE; } else if (argc == 3 && (strcasecmp(argv[2], "-a") == 0 || strcasecmp(argv[2], "--all") == 0)) { diff --git a/wiringPi/Makefile b/wiringPi/Makefile index dae51cf..2598a4c 100644 --- a/wiringPi/Makefile +++ b/wiringPi/Makefile @@ -41,7 +41,7 @@ DEBUG = -O2 CC = gcc INCLUDE = -I. DEFS = -D_GNU_SOURCE -CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Winline $(INCLUDE) -pipe -fPIC +CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Winline -Wno-format-truncation $(INCLUDE) -pipe -fPIC LIBS = -lm -lpthread -lrt -lcrypt @@ -52,6 +52,17 @@ SRC = wiringPi.c \ wiringPiSPI.c wiringPiI2C.c \ piHiPri.c piThread.c \ softPwm.c softTone.c softServo.c \ + mcp23008.c mcp23016.c mcp23017.c \ + mcp23s08.c mcp23s17.c \ + sr595.c \ + pcf8574.c pcf8591.c \ + mcp3002.c mcp3004.c mcp4802.c mcp3422.c \ + max31855.c max5322.c ads1115.c \ + sn3218.c \ + bmp180.c htu21d.c ds18b20.c rht03.c \ + drcSerial.c drcNet.c \ + pseudoPins.c \ + wpiExtensions.c \ odroidc1.c \ odroidc2.c \ odroidxu3.c \ @@ -137,6 +148,32 @@ piThread.o: wiringPi.h softPwm.o: wiringPi.h softPwm.h softTone.o: wiringPi.h softTone.h softServo.o: wiringPi.h softServo.h +mcp23008.o: wiringPi.h wiringPiI2C.h mcp23x0817.h mcp23008.h +mcp23016.o: wiringPi.h wiringPiI2C.h mcp23016.h mcp23016reg.h +mcp23017.o: wiringPi.h wiringPiI2C.h mcp23x0817.h mcp23017.h +mcp23s08.o: wiringPi.h wiringPiSPI.h mcp23x0817.h mcp23s08.h +mcp23s17.o: wiringPi.h wiringPiSPI.h mcp23x0817.h mcp23s17.h +sr595.o: wiringPi.h sr595.h +pcf8574.o: wiringPi.h wiringPiI2C.h pcf8574.h +pcf8591.o: wiringPi.h wiringPiI2C.h pcf8591.h +mcp3002.o: wiringPi.h wiringPiSPI.h mcp3002.h +mcp3004.o: wiringPi.h wiringPiSPI.h mcp3004.h +mcp4802.o: wiringPi.h wiringPiSPI.h mcp4802.h +mcp3422.o: wiringPi.h wiringPiI2C.h mcp3422.h +max31855.o: wiringPi.h wiringPiSPI.h max31855.h +max5322.o: wiringPi.h wiringPiSPI.h max5322.h +ads1115.o: wiringPi.h wiringPiI2C.h ads1115.h +sn3218.o: wiringPi.h wiringPiI2C.h sn3218.h +bmp180.o: wiringPi.h wiringPiI2C.h bmp180.h +htu21d.o: wiringPi.h wiringPiI2C.h htu21d.h +ds18b20.o: wiringPi.h ds18b20.h +drcSerial.o: wiringPi.h wiringSerial.h drcSerial.h +pseudoPins.o: wiringPi.h pseudoPins.h +wpiExtensions.o: wiringPi.h mcp23008.h mcp23016.h mcp23017.h mcp23s08.h +wpiExtensions.o: mcp23s17.h sr595.h pcf8574.h pcf8591.h mcp3002.h mcp3004.h +wpiExtensions.o: mcp4802.h mcp3422.h max31855.h max5322.h ads1115.h sn3218.h +wpiExtensions.o: drcSerial.h pseudoPins.h bmp180.h htu21d.h ds18b20.h +wpiExtensions.o: wpiExtensions.h # ODROID Boards odroidc1.o : wiringPi.h odroidc1.h diff --git a/wiringPi/ads1115.c b/wiringPi/ads1115.c new file mode 100644 index 0000000..648e612 --- /dev/null +++ b/wiringPi/ads1115.c @@ -0,0 +1,293 @@ +/* + * ads1115.c: + * Extend wiringPi with the ADS1115 I2C 16-bit ADC + * Copyright (c) 2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +/* + ********************************************************************************* + * We're going to work in a hybrid mode to fit in with the wiringPi way of + * doing things, so there will be 4 analog pin which read the 4 single-ended + * channels as usual, also some fake digitalOutputs - these are the control + * registers that allow the user to put it into single/diff mode, set the + * gain and data rates. + ********************************************************************************* + */ + +#include +#include +#include + +#include +#include + +#include "ads1115.h" + +// Bits in the config register (it's a 16-bit register) + +#define CONFIG_OS_MASK (0x8000) // Operational Status Register +#define CONFIG_OS_SINGLE (0x8000) // Write - Starts a single-conversion + // Read 1 = Conversion complete + +// The multiplexor + +#define CONFIG_MUX_MASK (0x7000) + +// Differential modes + +#define CONFIG_MUX_DIFF_0_1 (0x0000) // Pos = AIN0, Neg = AIN1 (default) +#define CONFIG_MUX_DIFF_0_3 (0x1000) // Pos = AIN0, Neg = AIN3 +#define CONFIG_MUX_DIFF_1_3 (0x2000) // Pos = AIN1, Neg = AIN3 +#define CONFIG_MUX_DIFF_2_3 (0x3000) // Pos = AIN2, Neg = AIN3 (2nd differential channel) + +// Single-ended modes + +#define CONFIG_MUX_SINGLE_0 (0x4000) // AIN0 +#define CONFIG_MUX_SINGLE_1 (0x5000) // AIN1 +#define CONFIG_MUX_SINGLE_2 (0x6000) // AIN2 +#define CONFIG_MUX_SINGLE_3 (0x7000) // AIN3 + +// Programmable Gain Amplifier + +#define CONFIG_PGA_MASK (0x0E00) +#define CONFIG_PGA_6_144V (0x0000) // +/-6.144V range = Gain 2/3 +#define CONFIG_PGA_4_096V (0x0200) // +/-4.096V range = Gain 1 +#define CONFIG_PGA_2_048V (0x0400) // +/-2.048V range = Gain 2 (default) +#define CONFIG_PGA_1_024V (0x0600) // +/-1.024V range = Gain 4 +#define CONFIG_PGA_0_512V (0x0800) // +/-0.512V range = Gain 8 +#define CONFIG_PGA_0_256V (0x0A00) // +/-0.256V range = Gain 16 + +#define CONFIG_MODE (0x0100) // 0 is continuous, 1 is single-shot (default) + +// Data Rate + +#define CONFIG_DR_MASK (0x00E0) +#define CONFIG_DR_8SPS (0x0000) // 8 samples per second +#define CONFIG_DR_16SPS (0x0020) // 16 samples per second +#define CONFIG_DR_32SPS (0x0040) // 32 samples per second +#define CONFIG_DR_64SPS (0x0060) // 64 samples per second +#define CONFIG_DR_128SPS (0x0080) // 128 samples per second (default) +#define CONFIG_DR_475SPS (0x00A0) // 475 samples per second +#define CONFIG_DR_860SPS (0x00C0) // 860 samples per second + +// Comparator mode + +#define CONFIG_CMODE_MASK (0x0010) +#define CONFIG_CMODE_TRAD (0x0000) // Traditional comparator with hysteresis (default) +#define CONFIG_CMODE_WINDOW (0x0010) // Window comparator + +// Comparator polarity - the polarity of the output alert/rdy pin + +#define CONFIG_CPOL_MASK (0x0008) +#define CONFIG_CPOL_ACTVLOW (0x0000) // Active low (default) +#define CONFIG_CPOL_ACTVHI (0x0008) // Active high + +// Latching comparator - does the alert/rdy pin latch + +#define CONFIG_CLAT_MASK (0x0004) +#define CONFIG_CLAT_NONLAT (0x0000) // Non-latching comparator (default) +#define CONFIG_CLAT_LATCH (0x0004) // Latching comparator + +// Comparitor queue + +#define CONFIG_CQUE_MASK (0x0003) +#define CONFIG_CQUE_1CONV (0x0000) // Assert after one conversions +#define CONFIG_CQUE_2CONV (0x0001) // Assert after two conversions +#define CONFIG_CQUE_4CONV (0x0002) // Assert after four conversions +#define CONFIG_CQUE_NONE (0x0003) // Disable the comparator (default) + +#define CONFIG_DEFAULT (0x8583) // From the datasheet + + +static const uint16_t dataRates [8] = +{ + CONFIG_DR_8SPS, CONFIG_DR_16SPS, CONFIG_DR_32SPS, CONFIG_DR_64SPS, CONFIG_DR_128SPS, CONFIG_DR_475SPS, CONFIG_DR_860SPS +} ; + +static const uint16_t gains [6] = +{ + CONFIG_PGA_6_144V, CONFIG_PGA_4_096V, CONFIG_PGA_2_048V, CONFIG_PGA_1_024V, CONFIG_PGA_0_512V, CONFIG_PGA_0_256V +} ; + + +/* + * analogRead: + * Pin is the channel to sample on the device. + * Channels 0-3 are single ended inputs, + * channels 4-7 are the various differential combinations. + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + int chan = pin - node->pinBase ; + int16_t result ; + uint16_t config = CONFIG_DEFAULT ; + + chan &= 7 ; + +// Setup the configuration register + +// Set PGA/voltage range + + config &= ~CONFIG_PGA_MASK ; + config |= node->data0 ; + +// Set sample speed + + config &= ~CONFIG_DR_MASK ; + config |= node->data1 ; + +// Set single-ended channel or differential mode + + config &= ~CONFIG_MUX_MASK ; + + switch (chan) + { + case 0: config |= CONFIG_MUX_SINGLE_0 ; break ; + case 1: config |= CONFIG_MUX_SINGLE_1 ; break ; + case 2: config |= CONFIG_MUX_SINGLE_2 ; break ; + case 3: config |= CONFIG_MUX_SINGLE_3 ; break ; + + case 4: config |= CONFIG_MUX_DIFF_0_1 ; break ; + case 5: config |= CONFIG_MUX_DIFF_2_3 ; break ; + case 6: config |= CONFIG_MUX_DIFF_0_3 ; break ; + case 7: config |= CONFIG_MUX_DIFF_1_3 ; break ; + } + +// Start a single conversion + + config |= CONFIG_OS_SINGLE ; + config = __bswap_16 (config) ; + wiringPiI2CWriteReg16 (node->fd, 1, config) ; + +// Wait for the conversion to complete + + for (;;) + { + result = wiringPiI2CReadReg16 (node->fd, 1) ; + result = __bswap_16 (result) ; + if ((result & CONFIG_OS_MASK) != 0) + break ; + delayMicroseconds (100) ; + } + + result = wiringPiI2CReadReg16 (node->fd, 0) ; + result = __bswap_16 (result) ; + +// Sometimes with a 0v input on a single-ended channel the internal 0v reference +// can be higher than the input, so you get a negative result... + + if ( (chan < 4) && (result < 0) ) + return 0 ; + else + return (int)result ; +} + + +/* + * digitalWrite: + * It may seem odd to have a digital write here, but it's the best way + * to pass paramters into the chip in the wiringPi way of things. + * We have 2 digital registers: + * 0 is the gain control + * 1 is the data rate control + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int data) +{ + int chan = pin - node->pinBase ; + chan &= 3 ; + + if (chan == 0) // Gain Control + { + if ( (data < 0) || (data > 6) ) // Use default if out of range + data = 2 ; + node->data0 = gains [data] ; + } + else // Data rate control + { + if ( (data < 0) || (data > 7) ) // Use default if out of range + data = 4 ; + node->data1 = dataRates [data] ; // Bugfix 0-1 by "Eric de jong (gm)" - Thanks. + } + +} + + +/* + * analogWrite: + * We're using this to write to the 2 comparitor threshold registers. + * We could use a digitalWrite here but as it's an analog comparison + * then it feels better to do it this way. + ********************************************************************************* + */ + +static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int data) +{ + int chan = pin - node->pinBase ; + int reg ; + int16_t ndata ; + + chan &= 3 ; + + reg = chan + 2 ; + + /**/ if (data < -32767) + ndata = -32767 ; + else if (data > 32767) + ndata = 32767 ; + else + ndata = (int16_t)data ; + + ndata = __bswap_16 (ndata) ; + wiringPiI2CWriteReg16 (node->fd, reg, data) ; +} + + + +/* + * ads1115Setup: + * Create a new wiringPi device node for an ads1115 on the Pi's + * I2C interface. + ********************************************************************************* + */ + +int ads1115Setup (const int pinBase, int i2cAddr) +{ + struct wiringPiNodeStruct *node ; + int fd ; + + if ((fd = wiringPiI2CSetup (i2cAddr)) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, 8) ; + + node->fd = fd ; + node->data0 = CONFIG_PGA_4_096V ; // Gain in data0 + node->data1 = CONFIG_DR_128SPS ; // Samples/sec in data1 + node->analogRead = myAnalogRead ; + node->analogWrite = myAnalogWrite ; + node->digitalWrite = myDigitalWrite ; + + return TRUE ; +} diff --git a/wiringPi/ads1115.h b/wiringPi/ads1115.h new file mode 100644 index 0000000..5c91735 --- /dev/null +++ b/wiringPi/ads1115.h @@ -0,0 +1,55 @@ +/* + * ads1115.c: + * Extend wiringPi with the ADS1115 I2C 16-bit ADC + * Copyright (c) 2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +// Constants for some of the internal functions + +// Gain + +#define ADS1115_GAIN_6 0 +#define ADS1115_GAIN_4 1 +#define ADS1115_GAIN_2 2 +#define ADS1115_GAIN_1 3 +#define ADS1115_GAIN_HALF 4 +#define ADS1115_GAIN_QUARTER 5 + +// Data rate + +#define ADS1115_DR_8 0 +#define ADS1115_DR_16 1 +#define ADS1115_DR_32 2 +#define ADS1115_DR_64 3 +#define ADS1115_DR_128 4 +#define ADS1115_DR_250 5 +#define ADS1115_DR_475 6 +#define ADS1115_DR_860 7 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int ads1115Setup (int pinBase, int i2cAddress) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/bmp180.c b/wiringPi/bmp180.c new file mode 100644 index 0000000..bad4bb3 --- /dev/null +++ b/wiringPi/bmp180.c @@ -0,0 +1,237 @@ +/* + * bmp180.c: + * Extend wiringPi with the BMP180 I2C Pressure and Temperature + * sensor. This is used in the Pi Weather Station + * Copyright (c) 2016 Gordon Henderson + * + * Information from the document held at: + * http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf + * was very useful when building this code. + * + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include + +#include "wiringPi.h" +#include "wiringPiI2C.h" + +#include "bmp180.h" + +#undef DEBUG + +#define I2C_ADDRESS 0x77 +#define BMP180_OSS 0 + + +// Static calibration data +// The down-side of this is that there can only be one BMP180 in +// a system - which is practice isn't an issue as it's I2C +// address is fixed. + +static int16_t AC1, AC2, AC3 ; +static uint16_t AC4, AC5, AC6 ; +static int16_t VB1, VB2 ; +static int16_t MB, MC, MD ; + +static double c5, c6, mc, md, x0, x1, x2, yy0, yy1, yy2, p0, p1, p2 ; + +// Pressure & Temp variables + +uint32_t cPress, cTemp ; + +static int altitude ; + +/* + * read16: + * Quick hack to read the 16-bit data with the correct endian + ********************************************************************************* + */ + +uint16_t read16 (int fd, int reg) +{ + return (wiringPiI2CReadReg8 (fd, reg) << 8) | wiringPiI2CReadReg8 (fd, reg + 1) ; + +} + + +/* + * bmp180ReadTempPress: + * Does the hard work of reading the sensor + ********************************************************************************* + */ + +static void bmp180ReadTempPress (int fd) +{ + double fTemp, fPress ; + double tu, a ; + double pu, s, x, y, z ; + + uint8_t data [4] ; + +// Start a temperature sensor reading + + wiringPiI2CWriteReg8 (fd, 0xF4, 0x2E) ; + delay (5) ; + +// Read the raw data + + data [0] = wiringPiI2CReadReg8 (fd, 0xF6) ; + data [1] = wiringPiI2CReadReg8 (fd, 0xF7) ; + +// And calculate... + + tu = (data [0] * 256.0) + data [1] ; + + a = c5 * (tu - c6) ; + fTemp = a + (mc / (a + md)) ; + cTemp = (int)rint (((100.0 * fTemp) + 0.5) / 10.0) ; + +#ifdef DEBUG + printf ("fTemp: %f, cTemp: %6d\n", fTemp, cTemp) ; +#endif + +// Start a pressure snsor reading + + wiringPiI2CWriteReg8 (fd, 0xF4, 0x34 | (BMP180_OSS << 6)) ; + delay (5) ; + +// Read the raw data + + data [0] = wiringPiI2CReadReg8 (fd, 0xF6) ; + data [1] = wiringPiI2CReadReg8 (fd, 0xF7) ; + data [2] = wiringPiI2CReadReg8 (fd, 0xF8) ; + +// And calculate... + + pu = ((double)data [0] * 256.0) + (double)data [1] + ((double)data [2] / 256.0) ; + s = fTemp - 25.0 ; + x = (x2 * pow (s, 2.0)) + (x1 * s) + x0 ; + y = (yy2 * pow (s, 2.0)) + (yy1 * s) + yy0 ; + z = (pu - x) / y ; + fPress = (p2 * pow (z, 2.0)) + (p1 * z) + p0 ; + cPress = (int)rint (((100.0 * fPress) + 0.5) / 10.0) ; + +#ifdef DEBUG + printf ("fPress: %f, cPress: %6d\n", fPress, cPress) ; +#endif +} + + +/* + * myAnalogWrite: + * Write to a fake register to represent the height above sea level + * so that the peudo millibar register can read the pressure in mB + ********************************************************************************* + */ + +static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + int chan = pin - node->pinBase ; + + if (chan == 0) + altitude = value ; +} + +/* + * myAnalogRead: + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + int chan = pin - node->pinBase ; + + bmp180ReadTempPress (node->fd) ; + + /**/ if (chan == 0) // Read Temperature + return cTemp ; + else if (chan == 1) // Pressure + return cPress ; + else if (chan == 2) // Pressure in mB + return cPress / pow (1 - ((double)altitude / 44330.0), 5.255) ; + else + return -9999 ; + +} + + +/* + * bmp180Setup: + * Create a new instance of a PCF8591 I2C GPIO interface. We know it + * has 4 pins, (4 analog inputs and 1 analog output which we'll shadow + * input 0) so all we need to know here is the I2C address and the + * user-defined pin base. + ********************************************************************************* + */ + +int bmp180Setup (const int pinBase) +{ + double c3, c4, b1 ; + int fd ; + struct wiringPiNodeStruct *node ; + + if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, 4) ; + + node->fd = fd ; + node->analogRead = myAnalogRead ; + node->analogWrite = myAnalogWrite ; + +// Read calibration data + + AC1 = read16 (fd, 0xAA) ; + AC2 = read16 (fd, 0xAC) ; + AC3 = read16 (fd, 0xAE) ; + AC4 = read16 (fd, 0xB0) ; + AC5 = read16 (fd, 0xB2) ; + AC6 = read16 (fd, 0xB4) ; + VB1 = read16 (fd, 0xB6) ; + VB2 = read16 (fd, 0xB8) ; + MB = read16 (fd, 0xBA) ; + MC = read16 (fd, 0xBC) ; + MD = read16 (fd, 0xBE) ; + +// Calculate coefficients + + c3 = 160.0 * pow (2.0, -15.0) * AC3 ; + c4 = pow (10.0, -3.0) * pow(2.0,-15.0) * AC4 ; + b1 = pow (160.0, 2.0) * pow(2.0,-30.0) * VB1 ; + c5 = (pow (2.0, -15.0) / 160.0) * AC5 ; + c6 = AC6 ; + mc = (pow (2.0, 11.0) / pow(160.0,2.0)) * MC ; + md = MD / 160.0 ; + x0 = AC1 ; + x1 = 160.0 * pow (2.0, -13.0) * AC2 ; + x2 = pow (160.0, 2.0) * pow(2.0,-25.0) * VB2 ; + yy0 = c4 * pow (2.0, 15.0) ; + yy1 = c4 * c3 ; + yy2 = c4 * b1 ; + p0 = (3791.0 - 8.0) / 1600.0 ; + p1 = 1.0 - 7357.0 * pow (2.0, -20.0) ; + p2 = 3038.0 * 100.0 * pow (2.0, -36.0) ; + + return TRUE ; +} diff --git a/wiringPi/bmp180.h b/wiringPi/bmp180.h new file mode 100644 index 0000000..4a6d13a --- /dev/null +++ b/wiringPi/bmp180.h @@ -0,0 +1,34 @@ +/* + * bmp180.h: + * Extend wiringPi with the BMP180 I2C Pressure and Temperature + * sensor. + * Copyright (c) 2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int bmp180Setup (const int pinBase) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/drcNet.c b/wiringPi/drcNet.c new file mode 100644 index 0000000..7799e52 --- /dev/null +++ b/wiringPi/drcNet.c @@ -0,0 +1,405 @@ +/* + * drcNet.h: + * Extend wiringPi with the DRC Network protocol (e.g. to another Pi) + * Copyright (c) 2016-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "wiringPi.h" +#include "drcNet.h" +#include "../wiringPiD/drcNetCmd.h" + + +/* + * remoteReadline: + * Read in a line of data from the remote server, ending with a newline + * character which is not stored. Returns the length or < 0 on + * any sort of failure. + ********************************************************************************* + */ + +static int remoteReadline (int fd, char *buf, int max) +{ + int len = 0 ; + char c ; + + for (;;) + { + if (read (fd, &c, 1) < 1) + return -1 ; + + if (c == '\n') + return len ; + + *buf++ = c ; + if (++len == max) + return len ; + } +} + + +/* + * getChallenge: + * Read in lines from the remote site until we get one identified + * as the challenge. This line contains the password salt. + ********************************************************************************* + */ + +static char *getChallenge (int fd) +{ + static char buf [1024] ; + int num ; + + for (;;) + { + if ((num = remoteReadline (fd, buf, 1023)) < 0) + return NULL ; + buf [num] = 0 ; + + if (strncmp (buf, "Challenge ", 10) == 0) + return &buf [10] ; + } +} + + +/* + * authenticate: + * Read in the challenge from the server, use it to encrypt our password + * and send it back to the server. Wait for a reply back from the server + * to say that we're good to go. + * The server will simply disconnect on a bad response. No 3 chances here. + ********************************************************************************* + */ + +static int authenticate (int fd, const char *pass) +{ + char *challenge ; + char *encrypted ; + char salted [1024] ; + + if ((challenge = getChallenge (fd)) == NULL) + return -1 ; + + snprintf (salted, 1024, "$6$%s$", challenge) ; + encrypted = crypt (pass, salted) ; + +// This is an assertion, or sanity check on my part... +// The '20' comes from the $6$ then the 16 characters of the salt, +// then the terminating $. + + if (strncmp (encrypted, salted, 20) != 0) + { + errno = EBADE ; + return -1 ; + } + +// 86 characters is the length of the SHA-256 hash + + if (write (fd, encrypted + 20, 86) == 86) + return 0 ; + else + return -1 ; +} + + +/* + * _drcSetupNet: + * Do the hard work of establishing a network connection and authenticating + * the password. + ********************************************************************************* + */ + +int _drcSetupNet (const char *ipAddress, const char *port, const char *password) +{ + struct addrinfo hints; + struct addrinfo *result, *rp ; + struct in6_addr serveraddr ; + int remoteFd ; + +// Start by seeing if we've been given a (textual) numeric IP address +// which will save lookups in getaddrinfo() + + memset (&hints, 0, sizeof (hints)) ; + hints.ai_flags = AI_NUMERICSERV ; + hints.ai_family = AF_UNSPEC ; + hints.ai_socktype = SOCK_STREAM ; + hints.ai_protocol = 0 ; + + if (inet_pton (AF_INET, ipAddress, &serveraddr) == 1) // Valid IPv4 + { + hints.ai_family = AF_INET ; + hints.ai_flags |= AI_NUMERICHOST ; + } + else + { + if (inet_pton (AF_INET6, ipAddress, &serveraddr) == 1) // Valid IPv6 + { + hints.ai_family = AF_INET6 ; + hints.ai_flags |= AI_NUMERICHOST ; + } + } + +// Now use getaddrinfo() with the newly supplied hints + + if (getaddrinfo (ipAddress, port, &hints, &result) != 0) + return -1 ; + +// Now try each address in-turn until we get one that connects... + + for (rp = result; rp != NULL; rp = rp->ai_next) + { + if ((remoteFd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0) + continue ; + + if (connect (remoteFd, rp->ai_addr, rp->ai_addrlen) < 0) + continue ; + + if (authenticate (remoteFd, password) < 0) + { + close (remoteFd) ; + errno = EACCES ; // Permission denied + return -1 ; + } + else + return remoteFd ; + } + + errno = EHOSTUNREACH ; // Host unreachable - may not be right, but good enough + return -1 ; // Nothing connected +} + + +/* + * myPinMode: + * Change the pin mode on the remote DRC device + ********************************************************************************* + */ + +static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_PIN_MODE ; + cmd.data = mode ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + + +/* + * myPullUpDnControl: + ********************************************************************************* + */ + +static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_PULL_UP_DN ; + cmd.data = mode ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + + +/* + * myDigitalWrite: + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_DIGITAL_WRITE ; + cmd.data = value ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + + +/* + * myDigitalWrite8: + ********************************************************************************* + +static void myDigitalWrite8 (struct wiringPiNodeStruct *node, int pin, int value) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_DIGITAL_WRITE8 ; + cmd.data = value ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + */ + + +/* + * myAnalogWrite: + ********************************************************************************* + */ + +static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_ANALOG_WRITE ; + cmd.data = value ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + + +/* + * myPwmWrite: + ********************************************************************************* + */ + +static void myPwmWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_PWM_WRITE ; + cmd.data = value ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; +} + + +/* + * myAnalogRead: + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_ANALOG_READ ; + cmd.data = 0 ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; + + return cmd.data ; +} + + +/* + * myDigitalRead: + ********************************************************************************* + */ + +static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_DIGITAL_READ ; + cmd.data = 0 ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; + + return cmd.data ; +} + + +/* + * myDigitalRead8: + ********************************************************************************* + +static unsigned int myDigitalRead8 (struct wiringPiNodeStruct *node, int pin) +{ + struct drcNetComStruct cmd ; + + cmd.pin = pin - node->pinBase ; + cmd.cmd = DRCN_DIGITAL_READ8 ; + cmd.data = 0 ; + + (void)send (node->fd, &cmd, sizeof (cmd), 0) ; + (void)recv (node->fd, &cmd, sizeof (cmd), 0) ; + + return cmd.data ; +} + */ + + +/* + * drcNet: + * Create a new instance of an DRC GPIO interface. + * Could be a variable nunber of pins here - we might not know in advance. + ********************************************************************************* + */ + +int drcSetupNet (const int pinBase, const int numPins, const char *ipAddress, const char *port, const char *password) +{ + int fd, len ; + struct wiringPiNodeStruct *node ; + + if ((fd = _drcSetupNet (ipAddress, port, password)) < 0) + return FALSE ; + + len = sizeof (struct drcNetComStruct) ; + + if (setsockopt (fd, SOL_SOCKET, SO_RCVLOWAT, (void *)&len, sizeof (len)) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, numPins) ; + + node->fd = fd ; + node->pinMode = myPinMode ; + node->pullUpDnControl = myPullUpDnControl ; + node->analogRead = myAnalogRead ; + node->analogRead = myAnalogRead ; + node->analogWrite = myAnalogWrite ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; +//node->digitalRead8 = myDigitalRead8 ; +//node->digitalWrite8 = myDigitalWrite8 ; + node->pwmWrite = myPwmWrite ; + + return TRUE ; +} diff --git a/wiringPi/drcNet.h b/wiringPi/drcNet.h new file mode 100644 index 0000000..00f9b05 --- /dev/null +++ b/wiringPi/drcNet.h @@ -0,0 +1,42 @@ +/* + * drcNet.h: + * Extend wiringPi with the DRC Network protocol (e.g. to another Pi) + * Copyright (c) 2016-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +/********* +struct drcNetStruct +{ + uint32_t pin ; + uint32_t cmd ; + uint32_t data ; +} ; +**************/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int drcSetupNet (const int pinBase, const int numPins, const char *ipAddress, const char *port, const char *password) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/drcSerial.c b/wiringPi/drcSerial.c new file mode 100644 index 0000000..db7cc09 --- /dev/null +++ b/wiringPi/drcSerial.c @@ -0,0 +1,196 @@ +/* + * drcSerial.c: + * Extend wiringPi with the DRC Serial protocol (e.g. to Arduino) + * Copyright (c) 2013-2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include + +#include "wiringPi.h" +#include "wiringSerial.h" + +#include "drcSerial.h" + + +/* + * myPinMode: + * Change the pin mode on the remote DRC device + ********************************************************************************* + */ + +static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode) +{ + /**/ if (mode == OUTPUT) + serialPutchar (node->fd, 'o') ; // Input + else if (mode == PWM_OUTPUT) + serialPutchar (node->fd, 'p') ; // PWM + else + serialPutchar (node->fd, 'i') ; // Default to input + + serialPutchar (node->fd, pin - node->pinBase) ; +} + + +/* + * myPullUpDnControl: + * ATmegas only have pull-up's on of off. No pull-downs. + ********************************************************************************* + */ + +static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode) +{ + +// Force pin into input mode + + serialPutchar (node->fd, 'i' ) ; + serialPutchar (node->fd, pin - node->pinBase) ; + + /**/ if (mode == PUD_UP) + { + serialPutchar (node->fd, '1') ; + serialPutchar (node->fd, pin - node->pinBase) ; + } + else if (mode == PUD_OFF) + { + serialPutchar (node->fd, '0') ; + serialPutchar (node->fd, pin - node->pinBase) ; + } +} + + +/* + * myDigitalWrite: + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + serialPutchar (node->fd, value == 0 ? '0' : '1') ; + serialPutchar (node->fd, pin - node->pinBase) ; +} + + +/* + * myPwmWrite: + ********************************************************************************* + */ + +static void myPwmWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + serialPutchar (node->fd, 'v') ; + serialPutchar (node->fd, pin - node->pinBase) ; + serialPutchar (node->fd, value & 0xFF) ; +} + + +/* + * myAnalogRead: + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + int vHi, vLo ; + + serialPutchar (node->fd, 'a') ; + serialPutchar (node->fd, pin - node->pinBase) ; + vHi = serialGetchar (node->fd) ; + vLo = serialGetchar (node->fd) ; + + return (vHi << 8) | vLo ; +} + + +/* + * myDigitalRead: + ********************************************************************************* + */ + +static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + serialPutchar (node->fd, 'r') ; // Send read command + serialPutchar (node->fd, pin - node->pinBase) ; + return (serialGetchar (node->fd) == '0') ? 0 : 1 ; +} + + +/* + * drcSetup: + * Create a new instance of an DRC GPIO interface. + * Could be a variable nunber of pins here - we might not know in advance + * if it's an ATmega with 14 pins, or something with less or more! + ********************************************************************************* + */ + +int drcSetupSerial (const int pinBase, const int numPins, const char *device, const int baud) +{ + int fd ; + int ok, tries ; + time_t then ; + struct wiringPiNodeStruct *node ; + + if ((fd = serialOpen (device, baud)) < 0) + return FALSE ; + + delay (10) ; // May need longer if it's an Uno that reboots on the open... + +// Flush any pending input + + while (serialDataAvail (fd)) + (void)serialGetchar (fd) ; + + ok = FALSE ; + for (tries = 1 ; (tries < 5) && (!ok) ; ++tries) + { + serialPutchar (fd, '@') ; // Ping + then = time (NULL) + 2 ; + while (time (NULL) < then) + if (serialDataAvail (fd)) + { + if (serialGetchar (fd) == '@') + { + ok = TRUE ; + break ; + } + } + } + + if (!ok) + { + serialClose (fd) ; + return FALSE ; + } + + node = wiringPiNewNode (pinBase, numPins) ; + + node->fd = fd ; + node->pinMode = myPinMode ; + node->pullUpDnControl = myPullUpDnControl ; + node->analogRead = myAnalogRead ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; + node->pwmWrite = myPwmWrite ; + + return TRUE ; +} diff --git a/wiringPi/drcSerial.h b/wiringPi/drcSerial.h new file mode 100644 index 0000000..29e988e --- /dev/null +++ b/wiringPi/drcSerial.h @@ -0,0 +1,33 @@ +/* + * drcSerial.h: + * Extend wiringPi with the DRC Serial protocol (e.g. to Arduino) + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int drcSetupSerial (const int pinBase, const int numPins, const char *device, const int baud) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/ds18b20.c b/wiringPi/ds18b20.c new file mode 100644 index 0000000..533398e --- /dev/null +++ b/wiringPi/ds18b20.c @@ -0,0 +1,146 @@ +/* + * ds18b20.c: + * Extend wiringPi with the DS18B20 1-Wire temperature sensor. + * This is used in the Pi Weather Station and many other places. + * Copyright (c) 2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "wiringPi.h" + +#include "ds18b20.h" + +#define W1_PREFIX "/sys/bus/w1/devices/28-" +#define W1_POSTFIX "/w1_slave" + + +/* + * myAnalogRead: + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + int chan = pin - node->pinBase ; + int fd = node->fd ; + char buffer [4096] ; + char *p ; + int temp, sign ; + + if (chan != 0) + return -9999 ; + +// Rewind the file - we're keeping it open to keep things going +// smoothly + + lseek (fd, 0, SEEK_SET) ; + +// Read the file - we know it's only a couple of lines, so this ought to be +// more than enough + + if (read (fd, buffer, 4096) <= 0) // Read nothing, or it failed in some odd way + return -9998 ; + +// Look for YES, then t= + + if (strstr (buffer, "YES") == NULL) + return -9997 ; + + if ((p = strstr (buffer, "t=")) == NULL) + return -9996 ; + +// p points to the 't', so we skip over it... + + p += 2 ; + +// and extract the number +// (without caring about overflow) + + + if (*p == '-') // Negative number? + { + sign = -1 ; + ++p ; + } + else + sign = 1 ; + + temp = 0 ; + while (isdigit (*p)) + { + temp = temp * 10 + (*p - '0') ; + ++p ; + } + +// We know it returns temp * 1000, but we only really want temp * 10, so +// do a bit of rounding... + + temp = (temp + 50) / 100 ; + return temp * sign ; +} + + +/* + * ds18b20Setup: + * Create a new instance of a DS18B20 temperature sensor. + ********************************************************************************* + */ + +int ds18b20Setup (const int pinBase, const char *deviceId) +{ + int fd ; + struct wiringPiNodeStruct *node ; + char *fileName ; + +// Allocate space for the filename + + if ((fileName = malloc (strlen (W1_PREFIX) + strlen (W1_POSTFIX) + strlen (deviceId) + 1)) == NULL) + return FALSE ; + + sprintf (fileName, "%s%s%s", W1_PREFIX, deviceId, W1_POSTFIX) ; + + fd = open (fileName, O_RDONLY) ; + + free (fileName) ; + + if (fd < 0) + return FALSE ; + +// We'll keep the file open, to make access a little faster +// although it's very slow reading these things anyway )-: + + node = wiringPiNewNode (pinBase, 1) ; + + node->fd = fd ; + node->analogRead = myAnalogRead ; + + return TRUE ; +} diff --git a/wiringPi/ds18b20.h b/wiringPi/ds18b20.h new file mode 100644 index 0000000..a9ea291 --- /dev/null +++ b/wiringPi/ds18b20.h @@ -0,0 +1,34 @@ +/* + * bmp180.h: + * Extend wiringPi with the BMP180 I2C Pressure and Temperature + * sensor. + * Copyright (c) 2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int ds18b20Setup (const int pinBase, const char *serialNum) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/htu21d.c b/wiringPi/htu21d.c new file mode 100644 index 0000000..46c0fcb --- /dev/null +++ b/wiringPi/htu21d.c @@ -0,0 +1,150 @@ +/* + * htu21d.c: + * Extend wiringPi with the HTU21D I2C humidity and Temperature + * sensor. This is used in the Pi Weather station. + * Copyright (c) 2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include + +#include "wiringPi.h" +#include "wiringPiI2C.h" + +#include "htu21d.h" + +#define DEBUG +#undef FAKE_SENSOR + +#define I2C_ADDRESS 0x40 + +int checksum (UNU uint8_t data [4]) +{ + return TRUE ; +} + + + +/* + * myAnalogRead: + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + int chan = pin - node->pinBase ; + int fd = node->fd ; + uint8_t data [4] ; + uint32_t sTemp, sHumid ; + double fTemp, fHumid ; + int cTemp, cHumid ; + + /**/ if (chan == 0) // Read Temperature + { + +// Send read temperature command: + + data [0] = 0xF3 ; + if (write (fd, data, 1) != 1) + return -9999 ; + +// Wait then read the data + + delay (50) ; + if (read (fd, data, 3) != 3) + return -9998 ; + + if (!checksum (data)) + return -9997 ; + +// Do the calculation + + sTemp = (data [0] << 8) | data [1] ; + fTemp = -48.85 + 175.72 * (double)sTemp / 63356.0 ; + cTemp = (int)rint (((100.0 * fTemp) + 0.5) / 10.0) ; + return cTemp ; + } + else if (chan == 1) // humidity + { +// Send read humidity command: + + data [0] = 0xF5 ; + if (write (fd, data, 1) != 1) + return -9999 ; + +// Wait then read the data + + delay (50) ; + if (read (fd, data, 3) != 3) + return -9998 ; + + if (!checksum (data)) + return -9997 ; + + sHumid = (data [0] << 8) | data [1] ; + fHumid = -6.0 + 125.0 * (double)sHumid / 65536.0 ; + cHumid = (int)rint (((100.0 * fHumid) + 0.5) / 10.0) ; + return cHumid ; + } + else + return -9999 ; +} + + +/* + * htu21dSetup: + * Create a new instance of a HTU21D I2C GPIO interface. + * This chip has a fixed I2C address, so we are not providing any + * allowance to change this. + ********************************************************************************* + */ + +int htu21dSetup (const int pinBase) +{ + int fd ; + struct wiringPiNodeStruct *node ; + uint8_t data ; + int status ; + + if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, 2) ; + + node->fd = fd ; + node->analogRead = myAnalogRead ; + +// Send a reset code to it: + + data = 0xFE ; + if (write (fd, &data, 1) != 1) + return FALSE ; + + delay (15) ; + +// Read the status register to check it's really there + + status = wiringPiI2CReadReg8 (fd, 0xE7) ; + + return (status == 0x02) ? TRUE : FALSE ; +} diff --git a/wiringPi/htu21d.h b/wiringPi/htu21d.h new file mode 100644 index 0000000..3965c54 --- /dev/null +++ b/wiringPi/htu21d.h @@ -0,0 +1,34 @@ +/* + * htu21d.h: + * Extend wiringPi with the HTU21D I2C Humidity and Temperature + * sensor. + * Copyright (c) 2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int htu21dSetup (const int pinBase) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/max31855.c b/wiringPi/max31855.c new file mode 100644 index 0000000..d86cabd --- /dev/null +++ b/wiringPi/max31855.c @@ -0,0 +1,99 @@ +/* + * max31855.c: + * Extend wiringPi with the max31855 SPI Analog to Digital convertor + * Copyright (c) 2012-2015 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include +#include + +#include "max31855.h" + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + uint32_t spiData ; + int temp ; + int chan = pin - node->pinBase ; + + wiringPiSPIDataRW (node->fd, (unsigned char *)&spiData, 4) ; + + spiData = __bswap_32(spiData) ; + + switch (chan) + { + case 0: // Existing read - return raw value * 4 + spiData >>= 18 ; + temp = spiData & 0x1FFF ; // Bottom 13 bits + if ((spiData & 0x2000) != 0) // Negative + temp = -temp ; + + return temp ; + + case 1: // Return error bits + return spiData & 0x7 ; + + case 2: // Return temp in C * 10 + spiData >>= 18 ; + temp = spiData & 0x1FFF ; // Bottom 13 bits + if ((spiData & 0x2000) != 0) // Negative + temp = -temp ; + + return (int)((((double)temp * 25) + 0.5) / 10.0) ; + + case 3: // Return temp in F * 10 + spiData >>= 18 ; + temp = spiData & 0x1FFF ; // Bottom 13 bits + if ((spiData & 0x2000) != 0) // Negative + temp = -temp ; + + return (int)((((((double)temp * 0.25 * 9.0 / 5.0) + 32.0) * 100.0) + 0.5) / 10.0) ; + + default: // Who knows... + return 0 ; + + } +} + + +/* + * max31855Setup: + * Create a new wiringPi device node for an max31855 on the Pi's + * SPI interface. + ********************************************************************************* + */ + +int max31855Setup (const int pinBase, int spiChannel) +{ + struct wiringPiNodeStruct *node ; + + if (wiringPiSPISetup (spiChannel, 5000000) < 0) // 5MHz - prob 4 on the Pi + return FALSE ; + + node = wiringPiNewNode (pinBase, 4) ; + + node->fd = spiChannel ; + node->analogRead = myAnalogRead ; + + return TRUE ; +} diff --git a/wiringPi/max31855.h b/wiringPi/max31855.h new file mode 100644 index 0000000..385c4bd --- /dev/null +++ b/wiringPi/max31855.h @@ -0,0 +1,33 @@ +/* + * max31855.c: + * Extend wiringPi with the MAX31855 SPI Thermocouple driver + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int max31855Setup (int pinBase, int spiChannel) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/max5322.c b/wiringPi/max5322.c new file mode 100644 index 0000000..e56b085 --- /dev/null +++ b/wiringPi/max5322.c @@ -0,0 +1,84 @@ +/* + * max5322.c: + * Extend wiringPi with the MAX5322 SPI Digital to Analog convertor + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "max5322.h" + +/* + * myAnalogWrite: + * Write analog value on the given pin + ********************************************************************************* + */ + +static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + unsigned char spiData [2] ; + unsigned char chanBits, dataBits ; + int chan = pin - node->pinBase ; + + if (chan == 0) + chanBits = 0b01000000 ; + else + chanBits = 0b01010000 ; + + chanBits |= ((value >> 12) & 0x0F) ; + dataBits = ((value ) & 0xFF) ; + + spiData [0] = chanBits ; + spiData [1] = dataBits ; + + wiringPiSPIDataRW (node->fd, spiData, 2) ; +} + +/* + * max5322Setup: + * Create a new wiringPi device node for an max5322 on the Pi's + * SPI interface. + ********************************************************************************* + */ + +int max5322Setup (const int pinBase, int spiChannel) +{ + struct wiringPiNodeStruct *node ; + unsigned char spiData [2] ; + + if (wiringPiSPISetup (spiChannel, 8000000) < 0) // 10MHz Max + return FALSE ; + + node = wiringPiNewNode (pinBase, 2) ; + + node->fd = spiChannel ; + node->analogWrite = myAnalogWrite ; + +// Enable both DACs + + spiData [0] = 0b11100000 ; + spiData [1] = 0 ; + + wiringPiSPIDataRW (node->fd, spiData, 2) ; + + return TRUE ; +} diff --git a/wiringPi/max5322.h b/wiringPi/max5322.h new file mode 100644 index 0000000..a217cf8 --- /dev/null +++ b/wiringPi/max5322.h @@ -0,0 +1,33 @@ +/* + * max5322.h: + * Extend wiringPi with the MAX5322 SPI Digital to Analog convertor + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int max5322Setup (int pinBase, int spiChannel) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/mcp23008.c b/wiringPi/mcp23008.c new file mode 100644 index 0000000..71757a8 --- /dev/null +++ b/wiringPi/mcp23008.c @@ -0,0 +1,149 @@ +/* + * mcp23008.c: + * Extend wiringPi with the MCP 23008 I2C GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "wiringPi.h" +#include "wiringPiI2C.h" +#include "mcp23x0817.h" + +#include "mcp23008.h" + + +/* + * myPinMode: + ********************************************************************************* + */ + +static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode) +{ + int mask, old, reg ; + + reg = MCP23x08_IODIR ; + mask = 1 << (pin - node->pinBase) ; + old = wiringPiI2CReadReg8 (node->fd, reg) ; + + if (mode == OUTPUT) + old &= (~mask) ; + else + old |= mask ; + + wiringPiI2CWriteReg8 (node->fd, reg, old) ; +} + + +/* + * myPullUpDnControl: + ********************************************************************************* + */ + +static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode) +{ + int mask, old, reg ; + + reg = MCP23x08_GPPU ; + mask = 1 << (pin - node->pinBase) ; + + old = wiringPiI2CReadReg8 (node->fd, reg) ; + + if (mode == PUD_UP) + old |= mask ; + else + old &= (~mask) ; + + wiringPiI2CWriteReg8 (node->fd, reg, old) ; +} + + +/* + * myDigitalWrite: + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + int bit, old ; + + bit = 1 << ((pin - node->pinBase) & 7) ; + + old = node->data2 ; + if (value == LOW) + old &= (~bit) ; + else + old |= bit ; + + wiringPiI2CWriteReg8 (node->fd, MCP23x08_GPIO, old) ; + node->data2 = old ; +} + + +/* + * myDigitalRead: + ********************************************************************************* + */ + +static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + int mask, value ; + + mask = 1 << ((pin - node->pinBase) & 7) ; + value = wiringPiI2CReadReg8 (node->fd, MCP23x08_GPIO) ; + + if ((value & mask) == 0) + return LOW ; + else + return HIGH ; +} + + +/* + * mcp23008Setup: + * Create a new instance of an MCP23008 I2C GPIO interface. We know it + * has 8 pins, so all we need to know here is the I2C address and the + * user-defined pin base. + ********************************************************************************* + */ + +int mcp23008Setup (const int pinBase, const int i2cAddress) +{ + int fd ; + struct wiringPiNodeStruct *node ; + + if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) + return FALSE ; + + wiringPiI2CWriteReg8 (fd, MCP23x08_IOCON, IOCON_INIT) ; + + node = wiringPiNewNode (pinBase, 8) ; + + node->fd = fd ; + node->pinMode = myPinMode ; + node->pullUpDnControl = myPullUpDnControl ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; + node->data2 = wiringPiI2CReadReg8 (fd, MCP23x08_OLAT) ; + + return TRUE ; +} diff --git a/wiringPi/mcp23008.h b/wiringPi/mcp23008.h new file mode 100644 index 0000000..e9299a8 --- /dev/null +++ b/wiringPi/mcp23008.h @@ -0,0 +1,33 @@ +/* + * 23008.h: + * Extend wiringPi with the MCP 23008 I2C GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mcp23008Setup (const int pinBase, const int i2cAddress) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/mcp23016.c b/wiringPi/mcp23016.c new file mode 100644 index 0000000..928d9e5 --- /dev/null +++ b/wiringPi/mcp23016.c @@ -0,0 +1,164 @@ +/* + * mcp23016.c: + * Extend wiringPi with the MCP 23016 I2C GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "wiringPi.h" +#include "wiringPiI2C.h" +#include "mcp23016.h" + +#include "mcp23016reg.h" + + +/* + * myPinMode: + ********************************************************************************* + */ + +static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode) +{ + int mask, old, reg ; + + pin -= node->pinBase ; + + if (pin < 8) // Bank A + reg = MCP23016_IODIR0 ; + else + { + reg = MCP23016_IODIR1 ; + pin &= 0x07 ; + } + + mask = 1 << pin ; + old = wiringPiI2CReadReg8 (node->fd, reg) ; + + if (mode == OUTPUT) + old &= (~mask) ; + else + old |= mask ; + + wiringPiI2CWriteReg8 (node->fd, reg, old) ; +} + + +/* + * myDigitalWrite: + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + int bit, old ; + + pin -= node->pinBase ; // Pin now 0-15 + + bit = 1 << (pin & 7) ; + + if (pin < 8) // Bank A + { + old = node->data2 ; + + if (value == LOW) + old &= (~bit) ; + else + old |= bit ; + + wiringPiI2CWriteReg8 (node->fd, MCP23016_GP0, old) ; + node->data2 = old ; + } + else // Bank B + { + old = node->data3 ; + + if (value == LOW) + old &= (~bit) ; + else + old |= bit ; + + wiringPiI2CWriteReg8 (node->fd, MCP23016_GP1, old) ; + node->data3 = old ; + } +} + + +/* + * myDigitalRead: + ********************************************************************************* + */ + +static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + int mask, value, gpio ; + + pin -= node->pinBase ; + + if (pin < 8) // Bank A + gpio = MCP23016_GP0 ; + else + { + gpio = MCP23016_GP1 ; + pin &= 0x07 ; + } + + mask = 1 << pin ; + value = wiringPiI2CReadReg8 (node->fd, gpio) ; + + if ((value & mask) == 0) + return LOW ; + else + return HIGH ; +} + + +/* + * mcp23016Setup: + * Create a new instance of an MCP23016 I2C GPIO interface. We know it + * has 16 pins, so all we need to know here is the I2C address and the + * user-defined pin base. + ********************************************************************************* + */ + +int mcp23016Setup (const int pinBase, const int i2cAddress) +{ + int fd ; + struct wiringPiNodeStruct *node ; + + if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) + return FALSE ; + + wiringPiI2CWriteReg8 (fd, MCP23016_IOCON0, IOCON_INIT) ; + wiringPiI2CWriteReg8 (fd, MCP23016_IOCON1, IOCON_INIT) ; + + node = wiringPiNewNode (pinBase, 16) ; + + node->fd = fd ; + node->pinMode = myPinMode ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; + node->data2 = wiringPiI2CReadReg8 (fd, MCP23016_OLAT0) ; + node->data3 = wiringPiI2CReadReg8 (fd, MCP23016_OLAT1) ; + + return TRUE ; +} diff --git a/wiringPi/mcp23016.h b/wiringPi/mcp23016.h new file mode 100644 index 0000000..f9b5cc5 --- /dev/null +++ b/wiringPi/mcp23016.h @@ -0,0 +1,33 @@ +/* + * mcp23016.h: + * Extend wiringPi with the MCP 23016 I2C GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mcp23016Setup (const int pinBase, const int i2cAddress) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/mcp23016reg.h b/wiringPi/mcp23016reg.h new file mode 100644 index 0000000..9aea92d --- /dev/null +++ b/wiringPi/mcp23016reg.h @@ -0,0 +1,48 @@ +/* + * mcp23016: + * Copyright (c) 2012-2013 Gordon Henderson + * + * Header file for code using the MCP23016 GPIO expander + * chip. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +// MCP23016 Registers + +#define MCP23016_GP0 0x00 +#define MCP23016_GP1 0x01 +#define MCP23016_OLAT0 0x02 +#define MCP23016_OLAT1 0x03 +#define MCP23016_IPOL0 0x04 +#define MCP23016_IPOL1 0x05 +#define MCP23016_IODIR0 0x06 +#define MCP23016_IODIR1 0x07 +#define MCP23016_INTCAP0 0x08 +#define MCP23016_INTCAP1 0x09 +#define MCP23016_IOCON0 0x0A +#define MCP23016_IOCON1 0x0B + +// Bits in the IOCON register + +#define IOCON_IARES 0x01 + +// Default initialisation mode + +#define IOCON_INIT 0 diff --git a/wiringPi/mcp23017.c b/wiringPi/mcp23017.c new file mode 100644 index 0000000..4c3952d --- /dev/null +++ b/wiringPi/mcp23017.c @@ -0,0 +1,195 @@ +/* + * mcp23017.c: + * Extend wiringPi with the MCP 23017 I2C GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "wiringPi.h" +#include "wiringPiI2C.h" +#include "mcp23x0817.h" + +#include "mcp23017.h" + + +/* + * myPinMode: + ********************************************************************************* + */ + +static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode) +{ + int mask, old, reg ; + + pin -= node->pinBase ; + + if (pin < 8) // Bank A + reg = MCP23x17_IODIRA ; + else + { + reg = MCP23x17_IODIRB ; + pin &= 0x07 ; + } + + mask = 1 << pin ; + old = wiringPiI2CReadReg8 (node->fd, reg) ; + + if (mode == OUTPUT) + old &= (~mask) ; + else + old |= mask ; + + wiringPiI2CWriteReg8 (node->fd, reg, old) ; +} + + +/* + * myPullUpDnControl: + ********************************************************************************* + */ + +static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode) +{ + int mask, old, reg ; + + pin -= node->pinBase ; + + if (pin < 8) // Bank A + reg = MCP23x17_GPPUA ; + else + { + reg = MCP23x17_GPPUB ; + pin &= 0x07 ; + } + + mask = 1 << pin ; + old = wiringPiI2CReadReg8 (node->fd, reg) ; + + if (mode == PUD_UP) + old |= mask ; + else + old &= (~mask) ; + + wiringPiI2CWriteReg8 (node->fd, reg, old) ; +} + + +/* + * myDigitalWrite: + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + int bit, old ; + + pin -= node->pinBase ; // Pin now 0-15 + + bit = 1 << (pin & 7) ; + + if (pin < 8) // Bank A + { + old = node->data2 ; + + if (value == LOW) + old &= (~bit) ; + else + old |= bit ; + + wiringPiI2CWriteReg8 (node->fd, MCP23x17_GPIOA, old) ; + node->data2 = old ; + } + else // Bank B + { + old = node->data3 ; + + if (value == LOW) + old &= (~bit) ; + else + old |= bit ; + + wiringPiI2CWriteReg8 (node->fd, MCP23x17_GPIOB, old) ; + node->data3 = old ; + } +} + + +/* + * myDigitalRead: + ********************************************************************************* + */ + +static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + int mask, value, gpio ; + + pin -= node->pinBase ; + + if (pin < 8) // Bank A + gpio = MCP23x17_GPIOA ; + else + { + gpio = MCP23x17_GPIOB ; + pin &= 0x07 ; + } + + mask = 1 << pin ; + value = wiringPiI2CReadReg8 (node->fd, gpio) ; + + if ((value & mask) == 0) + return LOW ; + else + return HIGH ; +} + + +/* + * mcp23017Setup: + * Create a new instance of an MCP23017 I2C GPIO interface. We know it + * has 16 pins, so all we need to know here is the I2C address and the + * user-defined pin base. + ********************************************************************************* + */ + +int mcp23017Setup (const int pinBase, const int i2cAddress) +{ + int fd ; + struct wiringPiNodeStruct *node ; + + if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) + return FALSE ; + + wiringPiI2CWriteReg8 (fd, MCP23x17_IOCON, IOCON_INIT) ; + + node = wiringPiNewNode (pinBase, 16) ; + + node->fd = fd ; + node->pinMode = myPinMode ; + node->pullUpDnControl = myPullUpDnControl ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; + node->data2 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATA) ; + node->data3 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATB) ; + + return TRUE ; +} diff --git a/wiringPi/mcp23017.h b/wiringPi/mcp23017.h new file mode 100644 index 0000000..79b4d7b --- /dev/null +++ b/wiringPi/mcp23017.h @@ -0,0 +1,33 @@ +/* + * 23017.h: + * Extend wiringPi with the MCP 23017 I2C GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mcp23017Setup (const int pinBase, const int i2cAddress) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/mcp23s08.c b/wiringPi/mcp23s08.c new file mode 100644 index 0000000..f293f3a --- /dev/null +++ b/wiringPi/mcp23s08.c @@ -0,0 +1,188 @@ +/* + * mcp23s08.c: + * Extend wiringPi with the MCP 23s08 SPI GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "wiringPi.h" +#include "wiringPiSPI.h" +#include "mcp23x0817.h" + +#include "mcp23s08.h" + +#define MCP_SPEED 4000000 + + + +/* + * writeByte: + * Write a byte to a register on the MCP23s08 on the SPI bus. + ********************************************************************************* + */ + +static void writeByte (uint8_t spiPort, uint8_t devId, uint8_t reg, uint8_t data) +{ + uint8_t spiData [4] ; + + spiData [0] = CMD_WRITE | ((devId & 7) << 1) ; + spiData [1] = reg ; + spiData [2] = data ; + + wiringPiSPIDataRW (spiPort, spiData, 3) ; +} + +/* + * readByte: + * Read a byte from a register on the MCP23s08 on the SPI bus. + ********************************************************************************* + */ + +static uint8_t readByte (uint8_t spiPort, uint8_t devId, uint8_t reg) +{ + uint8_t spiData [4] ; + + spiData [0] = CMD_READ | ((devId & 7) << 1) ; + spiData [1] = reg ; + + wiringPiSPIDataRW (spiPort, spiData, 3) ; + + return spiData [2] ; +} + + +/* + * myPinMode: + ********************************************************************************* + */ + +static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode) +{ + int mask, old, reg ; + + reg = MCP23x08_IODIR ; + mask = 1 << (pin - node->pinBase) ; + old = readByte (node->data0, node->data1, reg) ; + + if (mode == OUTPUT) + old &= (~mask) ; + else + old |= mask ; + + writeByte (node->data0, node->data1, reg, old) ; +} + + +/* + * myPullUpDnControl: + ********************************************************************************* + */ + +static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode) +{ + int mask, old, reg ; + + reg = MCP23x08_GPPU ; + mask = 1 << (pin - node->pinBase) ; + + old = readByte (node->data0, node->data1, reg) ; + + if (mode == PUD_UP) + old |= mask ; + else + old &= (~mask) ; + + writeByte (node->data0, node->data1, reg, old) ; +} + + +/* + * myDigitalWrite: + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + int bit, old ; + + bit = 1 << ((pin - node->pinBase) & 7) ; + + old = node->data2 ; + if (value == LOW) + old &= (~bit) ; + else + old |= bit ; + + writeByte (node->data0, node->data1, MCP23x08_GPIO, old) ; + node->data2 = old ; +} + + +/* + * myDigitalRead: + ********************************************************************************* + */ + +static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + int mask, value ; + + mask = 1 << ((pin - node->pinBase) & 7) ; + value = readByte (node->data0, node->data1, MCP23x08_GPIO) ; + + if ((value & mask) == 0) + return LOW ; + else + return HIGH ; +} + + +/* + * mcp23s08Setup: + * Create a new instance of an MCP23s08 SPI GPIO interface. We know it + * has 8 pins, so all we need to know here is the SPI address and the + * user-defined pin base. + ********************************************************************************* + */ + +int mcp23s08Setup (const int pinBase, const int spiPort, const int devId) +{ + struct wiringPiNodeStruct *node ; + + if (wiringPiSPISetup (spiPort, MCP_SPEED) < 0) + return FALSE ; + + writeByte (spiPort, devId, MCP23x08_IOCON, IOCON_INIT) ; + + node = wiringPiNewNode (pinBase, 8) ; + + node->data0 = spiPort ; + node->data1 = devId ; + node->pinMode = myPinMode ; + node->pullUpDnControl = myPullUpDnControl ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; + node->data2 = readByte (spiPort, devId, MCP23x08_OLAT) ; + + return TRUE ; +} diff --git a/wiringPi/mcp23s08.h b/wiringPi/mcp23s08.h new file mode 100644 index 0000000..ebf93d1 --- /dev/null +++ b/wiringPi/mcp23s08.h @@ -0,0 +1,33 @@ +/* + * 23s08.h: + * Extend wiringPi with the MCP 23s08 SPI GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mcp23s08Setup (const int pinBase, const int spiPort, const int devId) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/mcp23s17.c b/wiringPi/mcp23s17.c new file mode 100644 index 0000000..42b0358 --- /dev/null +++ b/wiringPi/mcp23s17.c @@ -0,0 +1,235 @@ +/* + * mcp23s17.c: + * Extend wiringPi with the MCP 23s17 SPI GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "wiringPi.h" +#include "wiringPiSPI.h" +#include "mcp23x0817.h" + +#include "mcp23s17.h" + +#define MCP_SPEED 4000000 + + + +/* + * writeByte: + * Write a byte to a register on the MCP23s17 on the SPI bus. + ********************************************************************************* + */ + +static void writeByte (uint8_t spiPort, uint8_t devId, uint8_t reg, uint8_t data) +{ + uint8_t spiData [4] ; + + spiData [0] = CMD_WRITE | ((devId & 7) << 1) ; + spiData [1] = reg ; + spiData [2] = data ; + + wiringPiSPIDataRW (spiPort, spiData, 3) ; +} + +/* + * readByte: + * Read a byte from a register on the MCP23s17 on the SPI bus. + ********************************************************************************* + */ + +static uint8_t readByte (uint8_t spiPort, uint8_t devId, uint8_t reg) +{ + uint8_t spiData [4] ; + + spiData [0] = CMD_READ | ((devId & 7) << 1) ; + spiData [1] = reg ; + + wiringPiSPIDataRW (spiPort, spiData, 3) ; + + return spiData [2] ; +} + + +/* + * myPinMode: + ********************************************************************************* + */ + +static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode) +{ + int mask, old, reg ; + + pin -= node->pinBase ; + + if (pin < 8) // Bank A + reg = MCP23x17_IODIRA ; + else + { + reg = MCP23x17_IODIRB ; + pin &= 0x07 ; + } + + mask = 1 << pin ; + old = readByte (node->data0, node->data1, reg) ; + + if (mode == OUTPUT) + old &= (~mask) ; + else + old |= mask ; + + writeByte (node->data0, node->data1, reg, old) ; +} + + +/* + * myPullUpDnControl: + ********************************************************************************* + */ + +static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode) +{ + int mask, old, reg ; + + pin -= node->pinBase ; + + if (pin < 8) // Bank A + reg = MCP23x17_GPPUA ; + else + { + reg = MCP23x17_GPPUB ; + pin &= 0x07 ; + } + + mask = 1 << pin ; + old = readByte (node->data0, node->data1, reg) ; + + if (mode == PUD_UP) + old |= mask ; + else + old &= (~mask) ; + + writeByte (node->data0, node->data1, reg, old) ; +} + + +/* + * myDigitalWrite: + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + int bit, old ; + + pin -= node->pinBase ; // Pin now 0-15 + + bit = 1 << (pin & 7) ; + + if (pin < 8) // Bank A + { + old = node->data2 ; + + if (value == LOW) + old &= (~bit) ; + else + old |= bit ; + + writeByte (node->data0, node->data1, MCP23x17_GPIOA, old) ; + node->data2 = old ; + } + else // Bank B + { + old = node->data3 ; + + if (value == LOW) + old &= (~bit) ; + else + old |= bit ; + + writeByte (node->data0, node->data1, MCP23x17_GPIOB, old) ; + node->data3 = old ; + } +} + + +/* + * myDigitalRead: + ********************************************************************************* + */ + +static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + int mask, value, gpio ; + + pin -= node->pinBase ; + + if (pin < 8) // Bank A + gpio = MCP23x17_GPIOA ; + else + { + gpio = MCP23x17_GPIOB ; + pin &= 0x07 ; + } + + mask = 1 << pin ; + value = readByte (node->data0, node->data1, gpio) ; + + if ((value & mask) == 0) + return LOW ; + else + return HIGH ; +} + + +/* + * mcp23s17Setup: + * Create a new instance of an MCP23s17 SPI GPIO interface. We know it + * has 16 pins, so all we need to know here is the SPI address and the + * user-defined pin base. + ********************************************************************************* + */ + +int mcp23s17Setup (const int pinBase, const int spiPort, const int devId) +{ + struct wiringPiNodeStruct *node ; + + if (wiringPiSPISetup (spiPort, MCP_SPEED) < 0) + return FALSE ; + + writeByte (spiPort, devId, MCP23x17_IOCON, IOCON_INIT | IOCON_HAEN) ; + writeByte (spiPort, devId, MCP23x17_IOCONB, IOCON_INIT | IOCON_HAEN) ; + + node = wiringPiNewNode (pinBase, 16) ; + + node->data0 = spiPort ; + node->data1 = devId ; + node->pinMode = myPinMode ; + node->pullUpDnControl = myPullUpDnControl ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; + node->data2 = readByte (spiPort, devId, MCP23x17_OLATA) ; + node->data3 = readByte (spiPort, devId, MCP23x17_OLATB) ; + + return TRUE ; +} diff --git a/wiringPi/mcp23s17.h b/wiringPi/mcp23s17.h new file mode 100644 index 0000000..3b2a808 --- /dev/null +++ b/wiringPi/mcp23s17.h @@ -0,0 +1,33 @@ +/* + * 23s17.h: + * Extend wiringPi with the MCP 23s17 SPI GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mcp23s17Setup (int pinBase, int spiPort, int devId) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/mcp23x08.h b/wiringPi/mcp23x08.h new file mode 100644 index 0000000..c4e6b27 --- /dev/null +++ b/wiringPi/mcp23x08.h @@ -0,0 +1,73 @@ +/* + * mcp23x17: + * Copyright (c) 2012-2013 Gordon Henderson + * + * Header file for code using the MCP23x17 GPIO expander chip. + * This comes in 2 flavours: MCP23017 which has an I2C interface, + * an the MXP23S17 which has an SPI interface. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + + +// MCP23x17 Registers + +#define IODIRA 0x00 +#define IPOLA 0x02 +#define GPINTENA 0x04 +#define DEFVALA 0x06 +#define INTCONA 0x08 +#define IOCON 0x0A +#define GPPUA 0x0C +#define INTFA 0x0E +#define INTCAPA 0x10 +#define GPIOA 0x12 +#define OLATA 0x14 + +#define IODIRB 0x01 +#define IPOLB 0x03 +#define GPINTENB 0x05 +#define DEFVALB 0x07 +#define INTCONB 0x09 +#define IOCONB 0x0B +#define GPPUB 0x0D +#define INTFB 0x0F +#define INTCAPB 0x11 +#define GPIOB 0x13 +#define OLATB 0x15 + +// Bits in the IOCON register + +#define IOCON_UNUSED 0x01 +#define IOCON_INTPOL 0x02 +#define IOCON_ODR 0x04 +#define IOCON_HAEN 0x08 +#define IOCON_DISSLW 0x10 +#define IOCON_SEQOP 0x20 +#define IOCON_MIRROR 0x40 +#define IOCON_BANK_MODE 0x80 + +// Default initialisation mode + +#define IOCON_INIT (IOCON_SEQOP) + +// SPI Command codes + +#define CMD_WRITE 0x40 +#define CMD_READ 0x41 diff --git a/wiringPi/mcp23x0817.h b/wiringPi/mcp23x0817.h new file mode 100644 index 0000000..58bc038 --- /dev/null +++ b/wiringPi/mcp23x0817.h @@ -0,0 +1,87 @@ +/* + * mcp23xxx: + * Copyright (c) 2012-2013 Gordon Henderson + * + * Header file for code using the MCP23x08 and 17 GPIO expander + * chips. + * This comes in 2 flavours: MCP230xx (08/17) which has an I2C + * interface, and the MXP23Sxx (08/17) which has an SPI interface. + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +// MCP23x08 Registers + +#define MCP23x08_IODIR 0x00 +#define MCP23x08_IPOL 0x01 +#define MCP23x08_GPINTEN 0x02 +#define MCP23x08_DEFVAL 0x03 +#define MCP23x08_INTCON 0x04 +#define MCP23x08_IOCON 0x05 +#define MCP23x08_GPPU 0x06 +#define MCP23x08_INTF 0x07 +#define MCP23x08_INTCAP 0x08 +#define MCP23x08_GPIO 0x09 +#define MCP23x08_OLAT 0x0A + +// MCP23x17 Registers + +#define MCP23x17_IODIRA 0x00 +#define MCP23x17_IPOLA 0x02 +#define MCP23x17_GPINTENA 0x04 +#define MCP23x17_DEFVALA 0x06 +#define MCP23x17_INTCONA 0x08 +#define MCP23x17_IOCON 0x0A +#define MCP23x17_GPPUA 0x0C +#define MCP23x17_INTFA 0x0E +#define MCP23x17_INTCAPA 0x10 +#define MCP23x17_GPIOA 0x12 +#define MCP23x17_OLATA 0x14 + +#define MCP23x17_IODIRB 0x01 +#define MCP23x17_IPOLB 0x03 +#define MCP23x17_GPINTENB 0x05 +#define MCP23x17_DEFVALB 0x07 +#define MCP23x17_INTCONB 0x09 +#define MCP23x17_IOCONB 0x0B +#define MCP23x17_GPPUB 0x0D +#define MCP23x17_INTFB 0x0F +#define MCP23x17_INTCAPB 0x11 +#define MCP23x17_GPIOB 0x13 +#define MCP23x17_OLATB 0x15 + +// Bits in the IOCON register + +#define IOCON_UNUSED 0x01 +#define IOCON_INTPOL 0x02 +#define IOCON_ODR 0x04 +#define IOCON_HAEN 0x08 +#define IOCON_DISSLW 0x10 +#define IOCON_SEQOP 0x20 +#define IOCON_MIRROR 0x40 +#define IOCON_BANK_MODE 0x80 + +// Default initialisation mode + +#define IOCON_INIT (IOCON_SEQOP) + +// SPI Command codes + +#define CMD_WRITE 0x40 +#define CMD_READ 0x41 diff --git a/wiringPi/mcp3002.c b/wiringPi/mcp3002.c new file mode 100644 index 0000000..9ebf3e4 --- /dev/null +++ b/wiringPi/mcp3002.c @@ -0,0 +1,76 @@ +/* + * mcp3002.c: + * Extend wiringPi with the MCP3002 SPI Analog to Digital convertor + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "mcp3002.h" + +/* + * myAnalogRead: + * Return the analog value of the given pin + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + unsigned char spiData [2] ; + unsigned char chanBits ; + int chan = pin - node->pinBase ; + + if (chan == 0) + chanBits = 0b11010000 ; + else + chanBits = 0b11110000 ; + + spiData [0] = chanBits ; + spiData [1] = 0 ; + + wiringPiSPIDataRW (node->fd, spiData, 2) ; + + return ((spiData [0] << 8) | (spiData [1] >> 1)) & 0x3FF ; +} + + +/* + * mcp3002Setup: + * Create a new wiringPi device node for an mcp3002 on the Pi's + * SPI interface. + ********************************************************************************* + */ + +int mcp3002Setup (const int pinBase, int spiChannel) +{ + struct wiringPiNodeStruct *node ; + + if (wiringPiSPISetup (spiChannel, 1000000) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, 2) ; + + node->fd = spiChannel ; + node->analogRead = myAnalogRead ; + + return TRUE ; +} diff --git a/wiringPi/mcp3002.h b/wiringPi/mcp3002.h new file mode 100644 index 0000000..0cd727f --- /dev/null +++ b/wiringPi/mcp3002.h @@ -0,0 +1,33 @@ +/* + * mcp3002.c: + * Extend wiringPi with the MCP3002 SPI Analog to Digital convertor + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mcp3002Setup (int pinBase, int spiChannel) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/mcp3004.c b/wiringPi/mcp3004.c new file mode 100644 index 0000000..be8383e --- /dev/null +++ b/wiringPi/mcp3004.c @@ -0,0 +1,76 @@ +/* + * mcp3004.c: + * Extend wiringPi with the MCP3004 SPI Analog to Digital convertor + * Copyright (c) 2012-2013 Gordon Henderson + * + * Thanks also to "ShorTie" on IRC for some remote debugging help! + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "mcp3004.h" + +/* + * myAnalogRead: + * Return the analog value of the given pin + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + unsigned char spiData [3] ; + unsigned char chanBits ; + int chan = pin - node->pinBase ; + + chanBits = 0b10000000 | (chan << 4) ; + + spiData [0] = 1 ; // Start bit + spiData [1] = chanBits ; + spiData [2] = 0 ; + + wiringPiSPIDataRW (node->fd, spiData, 3) ; + + return ((spiData [1] << 8) | spiData [2]) & 0x3FF ; +} + + +/* + * mcp3004Setup: + * Create a new wiringPi device node for an mcp3004 on the Pi's + * SPI interface. + ********************************************************************************* + */ + +int mcp3004Setup (const int pinBase, int spiChannel) +{ + struct wiringPiNodeStruct *node ; + + if (wiringPiSPISetup (spiChannel, 1000000) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, 8) ; + + node->fd = spiChannel ; + node->analogRead = myAnalogRead ; + + return TRUE ; +} diff --git a/wiringPi/mcp3004.h b/wiringPi/mcp3004.h new file mode 100644 index 0000000..a07c0bf --- /dev/null +++ b/wiringPi/mcp3004.h @@ -0,0 +1,33 @@ +/* + * mcp3004.c: + * Extend wiringPi with the MCP3004 SPI Analog to Digital convertor + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mcp3004Setup (int pinBase, int spiChannel) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/mcp3422.c b/wiringPi/mcp3422.c new file mode 100644 index 0000000..3999181 --- /dev/null +++ b/wiringPi/mcp3422.c @@ -0,0 +1,129 @@ +/* + * mcp3422.c: + * Extend wiringPi with the MCP3422/3/4 I2C ADC chip + * This code assumes single-ended mode only. + * Tested on actual hardware: 20th Feb 2016. + * Copyright (c) 2013-2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mcp3422.h" + + +/* + * waitForConversion: + * Common code to wait for the ADC to finish conversion + ********************************************************************************* + */ + +void waitForConversion (int fd, unsigned char *buffer, int n) +{ + for (;;) + { + if (read(fd, buffer, n) < 0) { + fprintf(stderr, "Unable to read from the file descriptor: %s \n", strerror(errno)); + } + if ((buffer [n-1] & 0x80) == 0) + break ; + delay (1) ; + } +} + +/* + * myAnalogRead: + * Read a channel from the device + ********************************************************************************* + */ + +int myAnalogRead (struct wiringPiNodeStruct *node, int chan) +{ + unsigned char config ; + unsigned char buffer [4] ; + int value = 0 ; + int realChan = (chan & 3) - node->pinBase ; + +// One-shot mode, trigger plus the other configs. + + config = 0x80 | (realChan << 5) | (node->data0 << 2) | (node->data1) ; + + wiringPiI2CWrite (node->fd, config) ; + + switch (node->data0) // Sample rate + { + case MCP3422_SR_3_75: // 18 bits + waitForConversion (node->fd, &buffer [0], 4) ; + value = ((buffer [0] & 3) << 16) | (buffer [1] << 8) | buffer [2] ; + break ; + + case MCP3422_SR_15: // 16 bits + waitForConversion (node->fd, buffer, 3) ; + value = (buffer [0] << 8) | buffer [1] ; + break ; + + case MCP3422_SR_60: // 14 bits + waitForConversion (node->fd, buffer, 3) ; + value = ((buffer [0] & 0x3F) << 8) | buffer [1] ; + break ; + + case MCP3422_SR_240: // 12 bits - default + waitForConversion (node->fd, buffer, 3) ; + value = ((buffer [0] & 0x0F) << 8) | buffer [1] ; + break ; + } + + return value ; +} + + +/* + * mcp3422Setup: + * Create a new wiringPi device node for the mcp3422 + ********************************************************************************* + */ + +int mcp3422Setup (int pinBase, int i2cAddress, int sampleRate, int gain) +{ + int fd ; + struct wiringPiNodeStruct *node ; + + if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, 4) ; + + node->fd = fd ; + node->data0 = sampleRate ; + node->data1 = gain ; + node->analogRead = myAnalogRead ; + + return TRUE ; +} diff --git a/wiringPi/mcp3422.h b/wiringPi/mcp3422.h new file mode 100644 index 0000000..72647d4 --- /dev/null +++ b/wiringPi/mcp3422.h @@ -0,0 +1,43 @@ +/* + * mcp3422.h: + * Extend wiringPi with the MCP3422/3/4 I2C ADC chip + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#define MCP3422_SR_240 0 +#define MCP3422_SR_60 1 +#define MCP3422_SR_15 2 +#define MCP3422_SR_3_75 3 + +#define MCP3422_GAIN_1 0 +#define MCP3422_GAIN_2 1 +#define MCP3422_GAIN_4 2 +#define MCP3422_GAIN_8 3 + + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mcp3422Setup (int pinBase, int i2cAddress, int sampleRate, int gain) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/mcp4802.c b/wiringPi/mcp4802.c new file mode 100644 index 0000000..ef104ed --- /dev/null +++ b/wiringPi/mcp4802.c @@ -0,0 +1,76 @@ +/* + * mcp4802.c: + * Extend wiringPi with the MCP4802 SPI Digital to Analog convertor + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "mcp4802.h" + +/* + * myAnalogWrite: + * Write analog value on the given pin + ********************************************************************************* + */ + +static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + unsigned char spiData [2] ; + unsigned char chanBits, dataBits ; + int chan = pin - node->pinBase ; + + if (chan == 0) + chanBits = 0x30 ; + else + chanBits = 0xB0 ; + + chanBits |= ((value >> 4) & 0x0F) ; + dataBits = ((value << 4) & 0xF0) ; + + spiData [0] = chanBits ; + spiData [1] = dataBits ; + + wiringPiSPIDataRW (node->fd, spiData, 2) ; +} + +/* + * mcp4802Setup: + * Create a new wiringPi device node for an mcp4802 on the Pi's + * SPI interface. + ********************************************************************************* + */ + +int mcp4802Setup (const int pinBase, int spiChannel) +{ + struct wiringPiNodeStruct *node ; + + if (wiringPiSPISetup (spiChannel, 1000000) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, 2) ; + + node->fd = spiChannel ; + node->analogWrite = myAnalogWrite ; + + return TRUE ; +} diff --git a/wiringPi/mcp4802.h b/wiringPi/mcp4802.h new file mode 100644 index 0000000..effa024 --- /dev/null +++ b/wiringPi/mcp4802.h @@ -0,0 +1,33 @@ +/* + * mcp4802.c: + * Extend wiringPi with the MCP4802 SPI Digital to Analog convertor + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mcp4802Setup (int pinBase, int spiChannel) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/pcf8574.c b/wiringPi/pcf8574.c new file mode 100644 index 0000000..e0b686a --- /dev/null +++ b/wiringPi/pcf8574.c @@ -0,0 +1,126 @@ +/* + * pcf8574.c: + * Extend wiringPi with the PCF8574 I2C GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "wiringPi.h" +#include "wiringPiI2C.h" + +#include "pcf8574.h" + + +/* + * myPinMode: + * The PCF8574 is an odd chip - the pins are effectively bi-directional, + * however the pins should be drven high when used as an input pin... + * So, we're effectively copying digitalWrite... + ********************************************************************************* + */ + +static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode) +{ + int bit, old ; + + bit = 1 << ((pin - node->pinBase) & 7) ; + + old = node->data2 ; + if (mode == OUTPUT) + old &= (~bit) ; // Write bit to 0 + else + old |= bit ; // Write bit to 1 + + wiringPiI2CWrite (node->fd, old) ; + node->data2 = old ; +} + + + +/* + * myDigitalWrite: + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + int bit, old ; + + bit = 1 << ((pin - node->pinBase) & 7) ; + + old = node->data2 ; + if (value == LOW) + old &= (~bit) ; + else + old |= bit ; + + wiringPiI2CWrite (node->fd, old) ; + node->data2 = old ; +} + + +/* + * myDigitalRead: + ********************************************************************************* + */ + +static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) +{ + int mask, value ; + + mask = 1 << ((pin - node->pinBase) & 7) ; + value = wiringPiI2CRead (node->fd) ; + + if ((value & mask) == 0) + return LOW ; + else + return HIGH ; +} + + +/* + * pcf8574Setup: + * Create a new instance of a PCF8574 I2C GPIO interface. We know it + * has 8 pins, so all we need to know here is the I2C address and the + * user-defined pin base. + ********************************************************************************* + */ + +int pcf8574Setup (const int pinBase, const int i2cAddress) +{ + int fd ; + struct wiringPiNodeStruct *node ; + + if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, 8) ; + + node->fd = fd ; + node->pinMode = myPinMode ; + node->digitalRead = myDigitalRead ; + node->digitalWrite = myDigitalWrite ; + node->data2 = wiringPiI2CRead (fd) ; + + return TRUE ; +} diff --git a/wiringPi/pcf8574.h b/wiringPi/pcf8574.h new file mode 100644 index 0000000..8e2d818 --- /dev/null +++ b/wiringPi/pcf8574.h @@ -0,0 +1,33 @@ +/* + * pcf8574.h: + * Extend wiringPi with the PCF8574 I2C GPIO expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int pcf8574Setup (const int pinBase, const int i2cAddress) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/pcf8591.c b/wiringPi/pcf8591.c new file mode 100644 index 0000000..cfb094a --- /dev/null +++ b/wiringPi/pcf8591.c @@ -0,0 +1,94 @@ +/* + * pcf8591.c: + * Extend wiringPi with the PCF8591 I2C GPIO Analog expander chip + * The chip has 1 8-bit DAC and 4 x 8-bit ADCs + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include +#include + +#include "wiringPi.h" +#include "wiringPiI2C.h" + +#include "pcf8591.h" + + +/* + * myAnalogWrite: + ********************************************************************************* + */ + +static void myAnalogWrite (struct wiringPiNodeStruct *node, UNU int pin, int value) +{ + unsigned char b [2] ; + b [0] = 0x40 ; + b [1] = value & 0xFF ; + if (write(node->fd, b, 2) < 0) { + fprintf(stderr, "Unable to write to the file descriptor: %s \n", strerror(errno)); + } +} + + +/* + * myAnalogRead: + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + int x ; + + wiringPiI2CWrite (node->fd, 0x40 | ((pin - node->pinBase) & 3)) ; + + x = wiringPiI2CRead (node->fd) ; // Throw away the first read + x = wiringPiI2CRead (node->fd) ; + + return x ; +} + + +/* + * pcf8591Setup: + * Create a new instance of a PCF8591 I2C GPIO interface. We know it + * has 4 pins, (4 analog inputs and 1 analog output which we'll shadow + * input 0) so all we need to know here is the I2C address and the + * user-defined pin base. + ********************************************************************************* + */ + +int pcf8591Setup (const int pinBase, const int i2cAddress) +{ + int fd ; + struct wiringPiNodeStruct *node ; + + if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) + return FALSE ; + + node = wiringPiNewNode (pinBase, 4) ; + + node->fd = fd ; + node->analogRead = myAnalogRead ; + node->analogWrite = myAnalogWrite ; + + return TRUE ; +} diff --git a/wiringPi/pcf8591.h b/wiringPi/pcf8591.h new file mode 100644 index 0000000..6b44ccf --- /dev/null +++ b/wiringPi/pcf8591.h @@ -0,0 +1,33 @@ +/* + * pcf8591.h: + * Extend wiringPi with the PCF8591 I2C GPIO Analog expander chip + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int pcf8591Setup (const int pinBase, const int i2cAddress) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/pseudoPins.c b/wiringPi/pseudoPins.c new file mode 100644 index 0000000..350b723 --- /dev/null +++ b/wiringPi/pseudoPins.c @@ -0,0 +1,95 @@ +/* + * pseudoPins.c: + * Extend wiringPi with a number of pseudo pins which can be + * digitally or analog written/read. + * + * Note: + * Just one set of pseudo pins can exist per Raspberry Pi. + * These pins are shared between all programs running on + * that Raspberry Pi. The values are also persistant as + * they live in shared RAM. This gives you a means for + * temporary variable storing/sharing between programs, + * or for other cunning things I've not thought of yet.. + * + * Copyright (c) 2012-2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#define SHARED_NAME "wiringPiPseudoPins" +#define PSEUDO_PINS 64 + +#include +#include +#include +#include +#include + +#include + +#include "pseudoPins.h" + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + int *ptr = (int *)(uintptr_t) node->data0 ; + int myPin = pin - node->pinBase ; + + return *(ptr + myPin) ; +} + + +static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + int *ptr = (int *)(uintptr_t) node->data0 ; + int myPin = pin - node->pinBase ; + + *(ptr + myPin) = value ; +} + + +/* + * pseudoPinsSetup: + * Create a new wiringPi device node for the pseudoPins driver + ********************************************************************************* + */ + +int pseudoPinsSetup (const int pinBase) +{ + struct wiringPiNodeStruct *node ; + void *ptr ; + + node = wiringPiNewNode (pinBase, PSEUDO_PINS) ; + + node->fd = shm_open (SHARED_NAME, O_CREAT | O_RDWR, 0666) ; + + if (node->fd < 0) + return FALSE ; + + if (ftruncate (node->fd, PSEUDO_PINS * sizeof (int)) < 0) + return FALSE ; + + ptr = mmap (NULL, PSEUDO_PINS * sizeof (int), PROT_READ | PROT_WRITE, MAP_SHARED, node->fd, 0) ; + + node->data0 = (unsigned int)(uintptr_t) ptr ; + + node->analogRead = myAnalogRead ; + node->analogWrite = myAnalogWrite ; + + return TRUE ; +} diff --git a/wiringPi/pseudoPins.h b/wiringPi/pseudoPins.h new file mode 100644 index 0000000..bef4660 --- /dev/null +++ b/wiringPi/pseudoPins.h @@ -0,0 +1,26 @@ +/* + * pseudoPins.h: + * Extend wiringPi with a number of pseudo pins which can be + * digitally or analog written/read. + * Copyright (c) 2012-2016 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +extern int pseudoPinsSetup (const int pinBase) ; diff --git a/wiringPi/rht03.c b/wiringPi/rht03.c new file mode 100644 index 0000000..1129cfd --- /dev/null +++ b/wiringPi/rht03.c @@ -0,0 +1,252 @@ +/* + * rht03.c: + * Extend wiringPi with the rht03 Maxdetect 1-Wire sensor. + * Copyright (c) 2016-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include + +#include "wiringPi.h" +#include "rht03.h" + +/* + * maxDetectLowHighWait: + * Wait for a transition from low to high on the bus + ********************************************************************************* + */ + +static int maxDetectLowHighWait (const int pin) +{ + struct timeval now, timeOut, timeUp ; + +// If already high then wait for pin to go low + + gettimeofday (&now, NULL) ; + timerclear (&timeOut) ; + timeOut.tv_usec = 1000 ; + timeradd (&now, &timeOut, &timeUp) ; + + while (digitalRead (pin) == HIGH) + { + gettimeofday (&now, NULL) ; + if (timercmp (&now, &timeUp, >)) + return FALSE ; + } + +// Wait for it to go HIGH + + gettimeofday (&now, NULL) ; + timerclear (&timeOut) ; + timeOut.tv_usec = 1000 ; + timeradd (&now, &timeOut, &timeUp) ; + + while (digitalRead (pin) == LOW) + { + gettimeofday (&now, NULL) ; + if (timercmp (&now, &timeUp, >)) + return FALSE ; + } + + return TRUE ; +} + + +/* + * maxDetectClockByte: + * Read in a single byte from the MaxDetect bus + ********************************************************************************* + */ + +static unsigned int maxDetectClockByte (const int pin) +{ + unsigned int byte = 0 ; + int bit ; + + for (bit = 0 ; bit < 8 ; ++bit) + { + if (!maxDetectLowHighWait (pin)) + return 0 ; + +// bit starting now - we need to time it. + + delayMicroseconds (30) ; + byte <<= 1 ; + if (digitalRead (pin) == HIGH) // It's a 1 + byte |= 1 ; + } + + return byte ; +} + + +/* + * maxDetectRead: + * Read in and return the 4 data bytes from the MaxDetect sensor. + * Return TRUE/FALSE depending on the checksum validity + ********************************************************************************* + */ + +static int maxDetectRead (const int pin, unsigned char buffer [4]) +{ + int i ; + unsigned int checksum ; + unsigned char localBuf [5] ; + struct timeval now, then, took ; + +// See how long we took + + gettimeofday (&then, NULL) ; + +// Wake up the RHT03 by pulling the data line low, then high +// Low for 10mS, high for 40uS. + + pinMode (pin, OUTPUT) ; + digitalWrite (pin, 0) ; delay (10) ; + digitalWrite (pin, 1) ; delayMicroseconds (40) ; + pinMode (pin, INPUT) ; + +// Now wait for sensor to pull pin low + + if (!maxDetectLowHighWait (pin)) + return FALSE ; + +// and read in 5 bytes (40 bits) + + for (i = 0 ; i < 5 ; ++i) + localBuf [i] = maxDetectClockByte (pin) ; + + checksum = 0 ; + for (i = 0 ; i < 4 ; ++i) + { + buffer [i] = localBuf [i] ; + checksum += localBuf [i] ; + } + checksum &= 0xFF ; + +// See how long we took + + gettimeofday (&now, NULL) ; + timersub (&now, &then, &took) ; + +// Total time to do this should be: +// 10mS + 40µS - reset +// + 80µS + 80µS - sensor doing its low -> high thing +// + 40 * (50µS + 27µS (0) or 70µS (1) ) +// = 15010µS +// so if we take more than that, we've had a scheduling interruption and the +// reading is probably bogus. + + if ((took.tv_sec != 0) || (took.tv_usec > 16000)) + return FALSE ; + + return checksum == localBuf [4] ; +} + + +/* + * myReadRHT03: + * Read the Temperature & Humidity from an RHT03 sensor + * Values returned are *10, so 123 is 12.3. + ********************************************************************************* + */ + +static int myReadRHT03 (const int pin, int *temp, int *rh) +{ + int result ; + unsigned char buffer [4] ; + +// Read ... + + result = maxDetectRead (pin, buffer) ; + + if (!result) + return FALSE ; + + *rh = (buffer [0] * 256 + buffer [1]) ; + *temp = (buffer [2] * 256 + buffer [3]) ; + + if ((*temp & 0x8000) != 0) // Negative + { + *temp &= 0x7FFF ; + *temp = -*temp ; + } + +// Discard obviously bogus readings - the checksum can't detect a 2-bit error +// (which does seem to happen - no realtime here) + + if ((*rh > 999) || (*temp > 800) || (*temp < -400)) + return FALSE ; + + return TRUE ; +} + + +/* + * myAnalogRead: + ********************************************************************************* + */ + +static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) +{ + int piPin = node->fd ; + int chan = pin - node->pinBase ; + int temp = -9997 ; + int rh = -9997 ; + int try ; + + if (chan > 1) + return -9999 ; // Bad parameters + + for (try = 0 ; try < 10 ; ++try) + { + if (myReadRHT03 (piPin, &temp, &rh)) + return chan == 0 ? temp : rh ; + } + + return -9998 ; +} + + +/* + * rht03Setup: + * Create a new instance of an RHT03 temperature sensor. + ********************************************************************************* + */ + +int rht03Setup (const int pinBase, const int piPin) +{ + struct wiringPiNodeStruct *node ; + + if ((piPin & PI_GPIO_MASK) != 0) // Must be an on-board pin + return FALSE ; + +// 2 pins - temperature and humidity + + node = wiringPiNewNode (pinBase, 2) ; + + node->fd = piPin ; + node->analogRead = myAnalogRead ; + + return TRUE ; +} diff --git a/wiringPi/rht03.h b/wiringPi/rht03.h new file mode 100644 index 0000000..9523fbf --- /dev/null +++ b/wiringPi/rht03.h @@ -0,0 +1,25 @@ +/* + * rht03.h: + * Extend wiringPi with the rht03 Maxdetect 1-Wire sensor. + * Copyright (c) 2016-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +extern int rht03Setup (const int pinBase, const int devicePin) ; diff --git a/wiringPi/sn3218.c b/wiringPi/sn3218.c new file mode 100644 index 0000000..d9b9113 --- /dev/null +++ b/wiringPi/sn3218.c @@ -0,0 +1,75 @@ +/* + * sn3218.c: + * Extend wiringPi with the SN3218 I2C LEd Driver + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "sn3218.h" + +/* + * myAnalogWrite: + * Write analog value on the given pin + ********************************************************************************* + */ + +static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + int fd = node->fd ; + int chan = 0x01 + (pin - node->pinBase) ; + + wiringPiI2CWriteReg8 (fd, chan, value & 0xFF) ; // Value + wiringPiI2CWriteReg8 (fd, 0x16, 0x00) ; // Update +} + +/* + * sn3218Setup: + * Create a new wiringPi device node for an sn3218 on the Pi's + * SPI interface. + ********************************************************************************* + */ + +int sn3218Setup (const int pinBase) +{ + int fd ; + struct wiringPiNodeStruct *node ; + + if ((fd = wiringPiI2CSetup (0x54)) < 0) + return FALSE ; + +// Setup the chip - initialise all 18 LEDs to off + +//wiringPiI2CWriteReg8 (fd, 0x17, 0) ; // Reset + wiringPiI2CWriteReg8 (fd, 0x00, 1) ; // Not Shutdown + wiringPiI2CWriteReg8 (fd, 0x13, 0x3F) ; // Enable LEDs 0- 5 + wiringPiI2CWriteReg8 (fd, 0x14, 0x3F) ; // Enable LEDs 6-11 + wiringPiI2CWriteReg8 (fd, 0x15, 0x3F) ; // Enable LEDs 12-17 + wiringPiI2CWriteReg8 (fd, 0x16, 0x00) ; // Update + + node = wiringPiNewNode (pinBase, 18) ; + + node->fd = fd ; + node->analogWrite = myAnalogWrite ; + + return TRUE ; +} diff --git a/wiringPi/sn3218.h b/wiringPi/sn3218.h new file mode 100644 index 0000000..580d5f9 --- /dev/null +++ b/wiringPi/sn3218.h @@ -0,0 +1,33 @@ +/* + * sn3218.c: + * Extend wiringPi with the SN3218 I2C LED driver board. + * Copyright (c) 2012-2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int sn3218Setup (int pinBase) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/sr595.c b/wiringPi/sr595.c new file mode 100644 index 0000000..8280618 --- /dev/null +++ b/wiringPi/sr595.c @@ -0,0 +1,109 @@ +/* + * sr595.c: + * Extend wiringPi with the 74x595 shift register as a GPIO + * expander chip. + * Note that the code can cope with a number of 595's + * daisy-chained together - up to 4 for now as we're storing + * the output "register" in a single unsigned int. + * + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#include +#include + +#include "wiringPi.h" + +#include "sr595.h" + + +/* + * myDigitalWrite: + ********************************************************************************* + */ + +static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value) +{ + unsigned int mask ; + int dataPin, clockPin, latchPin ; + int bit, bits, output ; + + pin -= node->pinBase ; // Normalise pin number + bits = node->pinMax - node->pinBase + 1 ; // ie. number of clock pulses + dataPin = node->data0 ; + clockPin = node->data1 ; + latchPin = node->data2 ; + output = node->data3 ; + + mask = 1 << pin ; + + if (value == LOW) + output &= (~mask) ; + else + output |= mask ; + + node->data3 = output ; + +// A low -> high latch transition copies the latch to the output pins + + digitalWrite (latchPin, LOW) ; delayMicroseconds (1) ; + for (bit = bits - 1 ; bit >= 0 ; --bit) + { + digitalWrite (dataPin, output & (1 << bit)) ; + + digitalWrite (clockPin, HIGH) ; delayMicroseconds (1) ; + digitalWrite (clockPin, LOW) ; delayMicroseconds (1) ; + } + digitalWrite (latchPin, HIGH) ; delayMicroseconds (1) ; +} + + +/* + * sr595Setup: + * Create a new instance of a 74x595 shift register GPIO expander. + ********************************************************************************* + */ + +int sr595Setup (const int pinBase, const int numPins, + const int dataPin, const int clockPin, const int latchPin) +{ + struct wiringPiNodeStruct *node ; + + node = wiringPiNewNode (pinBase, numPins) ; + + node->data0 = dataPin ; + node->data1 = clockPin ; + node->data2 = latchPin ; + node->data3 = 0 ; // Output register + node->digitalWrite = myDigitalWrite ; + +// Initialise the underlying hardware + + digitalWrite (dataPin, LOW) ; + digitalWrite (clockPin, LOW) ; + digitalWrite (latchPin, HIGH) ; + + pinMode (dataPin, OUTPUT) ; + pinMode (clockPin, OUTPUT) ; + pinMode (latchPin, OUTPUT) ; + + return TRUE ; +} diff --git a/wiringPi/sr595.h b/wiringPi/sr595.h new file mode 100644 index 0000000..4a26dc7 --- /dev/null +++ b/wiringPi/sr595.h @@ -0,0 +1,34 @@ +/* + * sr595.h: + * Extend wiringPi with the 74x595 shift registers. + * Copyright (c) 2013 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with wiringPi. + * If not, see . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int sr595Setup (const int pinBase, const int numPins, + const int dataPin, const int clockPin, const int latchPin) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 4c7f65a..9fde661 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -963,6 +963,74 @@ unsigned int micros (void) return (uint32_t)(now - libwiring.epochMicro); } +/*----------------------------------------------------------------------------*/ +// +// Unsupport Function list on ODROIDs +// +/*----------------------------------------------------------------------------*/ +static void UNU piGpioLayoutOops (const char UNU *why) { warn_msg(__func__); return; } + void gpioClockSet (int UNU pin, int UNU freq) { warn_msg(__func__); return; } + + /* core unsupport function */ + void pinModeAlt (int UNU pin, int UNU mode) { warn_msg(__func__); return; } + void analogWrite (int UNU pin, int UNU value) { warn_msg(__func__); return; } + void pwmToneWrite (int UNU pin, int UNU freq) { warn_msg(__func__); return; } + void digitalWriteByte2 (const int UNU value) { warn_msg(__func__); return; } + unsigned int digitalReadByte2 (void) { warn_msg(__func__); return -1; } + +/*----------------------------------------------------------------------------*/ +// Extend wiringPi with other pin-based devices and keep track of +// them in this structure +/*----------------------------------------------------------------------------*/ +struct wiringPiNodeStruct *wiringPiNodes = NULL ; + +struct wiringPiNodeStruct *wiringPiFindNode (int UNU pin) { return NULL; } + +static void pinModeDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode) { return ; } +static void pullUpDnControlDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int pud) { return ; } +static unsigned int UNU digitalRead8Dummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return 0 ; } +static void UNU digitalWrite8Dummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } +static int digitalReadDummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return LOW ; } +static void digitalWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } +static void pwmWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } +static int analogReadDummy (UNU struct wiringPiNodeStruct *node, UNU int pin) { return 0 ; } +static void analogWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } + +struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) +{ + int pin ; + struct wiringPiNodeStruct *node ; + + // Minimum pin base is 64 + if (pinBase < 64) + (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: pinBase of %d is < 64\n", pinBase) ; + + // Check all pins in-case there is overlap: + for (pin = pinBase ; pin < (pinBase + numPins) ; ++pin) + if (wiringPiFindNode (pin) != NULL) + (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Pin %d overlaps with existing definition\n", pin) ; + + node = (struct wiringPiNodeStruct *)calloc (sizeof (struct wiringPiNodeStruct), 1) ; // calloc zeros + if (node == NULL) + (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Unable to allocate memory: %s\n", strerror (errno)) ; + + node->pinBase = pinBase ; + node->pinMax = pinBase + numPins - 1 ; + node->pinMode = pinModeDummy ; + node->pullUpDnControl = pullUpDnControlDummy ; + node->digitalRead = digitalReadDummy ; + //node->digitalRead8 = digitalRead8Dummy ; + node->digitalWrite = digitalWriteDummy ; + //node->digitalWrite8 = digitalWrite8Dummy ; + node->pwmWrite = pwmWriteDummy ; + node->analogRead = analogReadDummy ; + node->analogWrite = analogWriteDummy ; + node->next = wiringPiNodes ; + wiringPiNodes = node ; + + return node ; +} + /*----------------------------------------------------------------------------*/ void wiringPiVersion (int *major, char **minor) { diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 473cfa2..893b692 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -98,6 +98,11 @@ #define WPI_FATAL (1==1) #define WPI_ALMOST (1==2) +// Legacy compatibility +// Mask for the bottom 64 pins which belong to the Raspberry Pi +// The others are available for the other devices +#define PI_GPIO_MASK (0xFFFFFFC0) + extern const char *piModelNames [16]; extern const char *piRevisionNames [16]; extern const char *piMakerNames [16]; @@ -196,6 +201,41 @@ union reg_bitfield { } bits; }; +/*----------------------------------------------------------------------------*/ +// wiringPiNodeStruct: +// This describes additional device nodes in the extended wiringPi +// 2.0 scheme of things. +// It's a simple linked list for now, but will hopefully migrate to +// a binary tree for efficiency reasons - but then again, the chances +// of more than 1 or 2 devices being added are fairly slim, so who +// knows.... +/*----------------------------------------------------------------------------*/ +struct wiringPiNodeStruct +{ + int pinBase; + int pinMax; + + int fd; // Node specific + unsigned int data0; // ditto + unsigned int data1; // ditto + unsigned int data2; // ditto + unsigned int data3; // ditto + + void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode); + void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode); + int (*digitalRead) (struct wiringPiNodeStruct *node, int pin); + // unsigned int (*digitalRead8) (struct wiringPiNodeStruct *node, int pin); + void (*digitalWrite) (struct wiringPiNodeStruct *node, int pin, int value); + // void (*digitalWrite8) (struct wiringPiNodeStruct *node, int pin, int value); + void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value); + int (*analogRead) (struct wiringPiNodeStruct *node, int pin); + void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value); + + struct wiringPiNodeStruct *next; +}; + +extern struct wiringPiNodeStruct *wiringPiNodes; + /*----------------------------------------------------------------------------*/ // Function prototypes // c++ wrappers thanks to a comment by Nick Lott @@ -205,6 +245,10 @@ union reg_bitfield { extern "C" { #endif +// Node supports for external boards +extern struct wiringPiNodeStruct *wiringPiFindNode (int pin); +extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins); + // Internal WiringPi functions extern int wiringPiFailure (int fatal, const char *message, ...); extern int msg (int type, const char *message, ...); @@ -261,6 +305,16 @@ extern void delayMicroseconds (unsigned int howLong); extern unsigned int millis (void); extern unsigned int micros (void); +// Unsupoorted +extern void pinModeAlt (int pin, int mode) UNU; +extern void analogWrite (int pin, int value) UNU; +extern void pwmToneWrite (int pin, int freq) UNU; +extern void gpioClockSet (int pin, int freq) UNU; +extern unsigned int digitalReadByte (void) UNU; +extern unsigned int digitalReadByte2 (void) UNU; +extern void digitalWriteByte (int value) UNU; +extern void digitalWriteByte2 (int value) UNU; + #ifdef __cplusplus } #endif diff --git a/wiringPi/wpiExtensions.c b/wiringPi/wpiExtensions.c new file mode 100644 index 0000000..bef126f --- /dev/null +++ b/wiringPi/wpiExtensions.c @@ -0,0 +1,928 @@ +/* + * extensions.c: + * Originally part of the GPIO program to test, peek, poke and otherwise + * noodle with the GPIO hardware on the Raspberry Pi. + * Now used as a general purpose library to allow systems to dynamically + * add in new devices into wiringPi at program run-time. + * Copyright (c) 2012-2015 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mcp23008.h" +#include "mcp23016.h" +#include "mcp23017.h" +#include "mcp23s08.h" +#include "mcp23s17.h" +#include "sr595.h" +#include "pcf8574.h" +#include "pcf8591.h" +#include "mcp3002.h" +#include "mcp3004.h" +#include "mcp4802.h" +#include "mcp3422.h" +#include "max31855.h" +#include "max5322.h" +#include "ads1115.h" +#include "sn3218.h" +#include "drcSerial.h" +#include "drcNet.h" +#include "../wiringPiD/drcNetCmd.h" +#include "pseudoPins.h" +#include "bmp180.h" +#include "htu21d.h" +#include "ds18b20.h" +#include "rht03.h" + +#include "wpiExtensions.h" + +extern int wiringPiDebug ; + +static int verbose ; +static char errorMessage [1024] ; + + +// Local structure to hold details + +struct extensionFunctionStruct +{ + const char *name ; + int (*function)(char *progName, int pinBase, char *params) ; +} ; + + +/* + * verbError: + * Convenient error handling + ********************************************************************************* + */ + +static void verbError (const char *message, ...) +{ + va_list argp ; + va_start (argp, message) ; + vsnprintf (errorMessage, 1023, message, argp) ; + va_end (argp) ; + + if (verbose) + fprintf (stderr, "%s\n", errorMessage) ; +} + + +/* + * extractInt: + * Check & return an integer at the given location (prefixed by a :) + ********************************************************************************* + */ + +static char *extractInt (char *progName, char *p, int *num) +{ + if (*p != ':') + { + verbError ("%s: colon expected", progName) ; + return NULL ; + } + + ++p ; + + if (!isdigit (*p)) + { + verbError ("%s: digit expected", progName) ; + return NULL ; + } + + *num = strtol (p, NULL, 0) ; + +// Increment p, but we need to check for hex 0x + + if ((*p == '0') && (*(p + 1) == 'x')) + p +=2 ; + + while (isxdigit (*p)) + ++p ; + + return p ; +} + + +/* + * extractStr: + * Check & return a string at the given location (prefixed by a :) + * Note: The string can be enclosed in []'s to escape colons. This is + * so we can handle IPv6 addresses which contain colons and the []'s is + * a common way to prepresent them. + ********************************************************************************* + */ + +static char *extractStr (char *progName, char *p, char **str) +{ + char *q, *r ; + int quoted = FALSE ; + + if (*p != ':') + { + verbError ("%s: colon expected", progName) ; + return NULL ; + } + + ++p ; + + if (*p == '[') + { + quoted = TRUE ; + ++p ; + } + + if (!isprint (*p)) // Is this needed? + { + verbError ("%s: character expected", progName) ; + return NULL ; + } + + q = p ; + if (quoted) + { + while ((*q != 0) && (*q != ']')) + ++q ; + } + else + { + while ((*q != 0) && (*q != ':')) + ++q ; + } + + *str = r = calloc (q - p + 2, 1) ; // Zeros it + + while (p != q) + *r++ = *p++ ; + + if (quoted) // Skip over the ] to the : + ++p ; + + return p ; +} + + + +/* + * doExtensionMcp23008: + * MCP23008 - 8-bit I2C GPIO expansion chip + * mcp23002:base:i2cAddr + ********************************************************************************* + */ + +static int doExtensionMcp23008 (char *progName, int pinBase, char *params) +{ + int i2c ; + + if ((params = extractInt (progName, params, &i2c)) == NULL) + return FALSE ; + + if ((i2c < 0x01) || (i2c > 0x77)) + { + verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; + return FALSE ; + } + + mcp23008Setup (pinBase, i2c) ; + + return TRUE ; +} + + +/* + * doExtensionMcp23016: + * MCP230016- 16-bit I2C GPIO expansion chip + * mcp23016:base:i2cAddr + ********************************************************************************* + */ + +static int doExtensionMcp23016 (char *progName, int pinBase, char *params) +{ + int i2c ; + + if ((params = extractInt (progName, params, &i2c)) == NULL) + return FALSE ; + + if ((i2c < 0x03) || (i2c > 0x77)) + { + verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; + return FALSE ; + } + + mcp23016Setup (pinBase, i2c) ; + + return TRUE ; +} + + +/* + * doExtensionMcp23017: + * MCP230017- 16-bit I2C GPIO expansion chip + * mcp23017:base:i2cAddr + ********************************************************************************* + */ + +static int doExtensionMcp23017 (char *progName, int pinBase, char *params) +{ + int i2c ; + + if ((params = extractInt (progName, params, &i2c)) == NULL) + return FALSE ; + + if ((i2c < 0x03) || (i2c > 0x77)) + { + verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; + return FALSE ; + } + + mcp23017Setup (pinBase, i2c) ; + + return TRUE ; +} + + +/* + * doExtensionMcp23s08: + * MCP23s08 - 8-bit SPI GPIO expansion chip + * mcp23s08:base:spi:port + ********************************************************************************* + */ + +static int doExtensionMcp23s08 (char *progName, int pinBase, char *params) +{ + int spi, port ; + + if ((params = extractInt (progName, params, &spi)) == NULL) + return FALSE ; + + if ((spi < 0) || (spi > 1)) + { + verbError ("%s: SPI address (%d) out of range", progName, spi) ; + return FALSE ; + } + + if ((params = extractInt (progName, params, &port)) == NULL) + return FALSE ; + + if ((port < 0) || (port > 7)) + { + verbError ("%s: port address (%d) out of range", progName, port) ; + return FALSE ; + } + + mcp23s08Setup (pinBase, spi, port) ; + + return TRUE ; +} + + +/* + * doExtensionMcp23s17: + * MCP23s17 - 16-bit SPI GPIO expansion chip + * mcp23s17:base:spi:port + ********************************************************************************* + */ + +static int doExtensionMcp23s17 (char *progName, int pinBase, char *params) +{ + int spi, port ; + + if ((params = extractInt (progName, params, &spi)) == NULL) + return FALSE ; + + if ((spi < 0) || (spi > 1)) + { + verbError ("%s: SPI address (%d) out of range", progName, spi) ; + return FALSE ; + } + + if ((params = extractInt (progName, params, &port)) == NULL) + return FALSE ; + + if ((port < 0) || (port > 7)) + { + verbError ("%s: port address (%d) out of range", progName, port) ; + return FALSE ; + } + + mcp23s17Setup (pinBase, spi, port) ; + + return TRUE ; +} + + +/* + * doExtensionSr595: + * Shift Register 74x595 + * sr595:base:pins:data:clock:latch + ********************************************************************************* + */ + +static int doExtensionSr595 (char *progName, int pinBase, char *params) +{ + int pins, data, clock, latch ; + +// Extract pins + + if ((params = extractInt (progName, params, &pins)) == NULL) + return FALSE ; + + if ((pins < 8) || (pins > 32)) + { + verbError ("%s: pin count (%d) out of range - 8-32 expected.", progName, pins) ; + return FALSE ; + } + + if ((params = extractInt (progName, params, &data)) == NULL) + return FALSE ; + + if ((params = extractInt (progName, params, &clock)) == NULL) + return FALSE ; + + if ((params = extractInt (progName, params, &latch)) == NULL) + return FALSE ; + + sr595Setup (pinBase, pins, data, clock, latch) ; + + return TRUE ; +} + + +/* + * doExtensionPcf8574: + * Digital IO (Crude!) + * pcf8574:base:i2cAddr + ********************************************************************************* + */ + +static int doExtensionPcf8574 (char *progName, int pinBase, char *params) +{ + int i2c ; + + if ((params = extractInt (progName, params, &i2c)) == NULL) + return FALSE ; + + if ((i2c < 0x03) || (i2c > 0x77)) + { + verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; + return FALSE ; + } + + pcf8574Setup (pinBase, i2c) ; + + return TRUE ; +} + + +/* + * doExtensionAds1115: + * Analog Input + * ads1115:base:i2cAddr + ********************************************************************************* + */ + +static int doExtensionAds1115 (char *progName, int pinBase, char *params) +{ + int i2c ; + + if ((params = extractInt (progName, params, &i2c)) == NULL) + return FALSE ; + + if ((i2c < 0x03) || (i2c > 0x77)) + { + verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; + return FALSE ; + } + + ads1115Setup (pinBase, i2c) ; + + return TRUE ; +} + + +/* + * doExtensionPcf8591: + * Analog IO + * pcf8591:base:i2cAddr + ********************************************************************************* + */ + +static int doExtensionPcf8591 (char *progName, int pinBase, char *params) +{ + int i2c ; + + if ((params = extractInt (progName, params, &i2c)) == NULL) + return FALSE ; + + if ((i2c < 0x03) || (i2c > 0x77)) + { + verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; + return FALSE ; + } + + pcf8591Setup (pinBase, i2c) ; + + return TRUE ; +} + + +/* + * doExtensionPseudoPins: + * 64 Memory resident pseudo pins + * pseudoPins:base + ********************************************************************************* + */ + +static int doExtensionPseudoPins (UNU char *progName, int pinBase, UNU char *params) +{ + pseudoPinsSetup (pinBase) ; + + return TRUE ; +} + + +/* + * doExtensionBmp180: + * Analog Temp + Pressure + * bmp180:base + ********************************************************************************* + */ + +static int doExtensionBmp180 (UNU char *progName, int pinBase, UNU char *params) +{ + bmp180Setup (pinBase) ; + + return TRUE ; +} + + +/* + * doExtensionHtu21d: + * Analog humidity + Pressure + * htu21d:base + ********************************************************************************* + */ + +static int doExtensionHtu21d (UNU char *progName, int pinBase, UNU char *params) +{ + htu21dSetup (pinBase) ; + + return TRUE ; +} + + +/* + * doExtensionDs18b20: + * 1-Wire Temperature + * htu21d:base:serialNum + ********************************************************************************* + */ + +static int doExtensionDs18b20 (char *progName, int pinBase, char *params) +{ + char *serialNum ; + + if ((params = extractStr (progName, params, &serialNum)) == NULL) + return FALSE ; + + return ds18b20Setup (pinBase, serialNum) ; +} + + +/* + * doExtensionRht03: + * Maxdetect 1-Wire Temperature & Humidity + * rht03:base:piPin + ********************************************************************************* + */ + +static int doExtensionRht03 (char *progName, int pinBase, char *params) +{ + int piPin ; + + if ((params = extractInt (progName, params, &piPin)) == NULL) + return FALSE ; + + return rht03Setup (pinBase, piPin) ; +} + + +/* + * doExtensionMax31855: + * Analog IO + * max31855:base:spiChan + ********************************************************************************* + */ + +static int doExtensionMax31855 (char *progName, int pinBase, char *params) +{ + int spi ; + + if ((params = extractInt (progName, params, &spi)) == NULL) + return FALSE ; + + if ((spi < 0) || (spi > 1)) + { + verbError ("%s: SPI channel (%d) out of range", progName, spi) ; + return FALSE ; + } + + max31855Setup (pinBase, spi) ; + + return TRUE ; +} + + +/* + * doExtensionMcp3002: + * Analog IO + * mcp3002:base:spiChan + ********************************************************************************* + */ + +static int doExtensionMcp3002 (char *progName, int pinBase, char *params) +{ + int spi ; + + if ((params = extractInt (progName, params, &spi)) == NULL) + return FALSE ; + + if ((spi < 0) || (spi > 1)) + { + verbError ("%s: SPI channel (%d) out of range", progName, spi) ; + return FALSE ; + } + + mcp3002Setup (pinBase, spi) ; + + return TRUE ; +} + + +/* + * doExtensionMcp3004: + * Analog IO + * mcp3004:base:spiChan + ********************************************************************************* + */ + +static int doExtensionMcp3004 (char *progName, int pinBase, char *params) +{ + int spi ; + + if ((params = extractInt (progName, params, &spi)) == NULL) + return FALSE ; + + if ((spi < 0) || (spi > 1)) + { + verbError ("%s: SPI channel (%d) out of range", progName, spi) ; + return FALSE ; + } + + mcp3004Setup (pinBase, spi) ; + + return TRUE ; +} + + +/* + * doExtensionMax5322: + * Analog O + * max5322:base:spiChan + ********************************************************************************* + */ + +static int doExtensionMax5322 (char *progName, int pinBase, char *params) +{ + int spi ; + + if ((params = extractInt (progName, params, &spi)) == NULL) + return FALSE ; + + if ((spi < 0) || (spi > 1)) + { + verbError ("%s: SPI channel (%d) out of range", progName, spi) ; + return FALSE ; + } + + max5322Setup (pinBase, spi) ; + + return TRUE ; +} + + +/* + * doExtensionMcp4802: + * Analog IO + * mcp4802:base:spiChan + ********************************************************************************* + */ + +static int doExtensionMcp4802 (char *progName, int pinBase, char *params) +{ + int spi ; + + if ((params = extractInt (progName, params, &spi)) == NULL) + return FALSE ; + + if ((spi < 0) || (spi > 1)) + { + verbError ("%s: SPI channel (%d) out of range", progName, spi) ; + return FALSE ; + } + + mcp4802Setup (pinBase, spi) ; + + return TRUE ; +} + + +/* + * doExtensionSn3218: + * Analog Output (LED Driver) + * sn3218:base + ********************************************************************************* + */ + +static int doExtensionSn3218 (UNU char *progName, int pinBase, UNU char *params) +{ + sn3218Setup (pinBase) ; + return TRUE ; +} + + +/* + * doExtensionMcp3422: + * Analog IO + * mcp3422:base:i2cAddr + ********************************************************************************* + */ + +static int doExtensionMcp3422 (char *progName, int pinBase, char *params) +{ + int i2c, sampleRate, gain ; + + if ((params = extractInt (progName, params, &i2c)) == NULL) + return FALSE ; + + if ((i2c < 0x03) || (i2c > 0x77)) + { + verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; + return FALSE ; + } + + if ((params = extractInt (progName, params, &sampleRate)) == NULL) + return FALSE ; + + if ((sampleRate < 0) || (sampleRate > 3)) + { + verbError ("%s: sample rate (%d) out of range", progName, sampleRate) ; + return FALSE ; + } + + if ((params = extractInt (progName, params, &gain)) == NULL) + return FALSE ; + + if ((gain < 0) || (gain > 3)) + { + verbError ("%s: gain (%d) out of range", progName, gain) ; + return FALSE ; + } + + mcp3422Setup (pinBase, i2c, sampleRate, gain) ; + + return TRUE ; +} + + +/* + * doExtensionDrcS: + * Interface to a DRC Serial system + * drcs:base:pins:serialPort:baud + ********************************************************************************* + */ + +static int doExtensionDrcS (char *progName, int pinBase, char *params) +{ + char *port ; + int pins, baud ; + + if ((params = extractInt (progName, params, &pins)) == NULL) + return FALSE ; + + if ((pins < 1) || (pins > 1000)) + { + verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ; + return FALSE ; + } + + if ((params = extractStr (progName, params, &port)) == NULL) + return FALSE ; + + if (strlen (port) == 0) + { + verbError ("%s: serial port device name required", progName) ; + return FALSE ; + } + + if ((params = extractInt (progName, params, &baud)) == NULL) + return FALSE ; + + if ((baud < 1) || (baud > 4000000)) + { + verbError ("%s: baud rate (%d) out of range", progName, baud) ; + return FALSE ; + } + + drcSetupSerial (pinBase, pins, port, baud) ; + + return TRUE ; +} + + +/* + * doExtensionDrcNet: + * Interface to a DRC Network system + * drcn:base:pins:ipAddress:port:password + ********************************************************************************* + */ + +static int doExtensionDrcNet (char *progName, int pinBase, char *params) +{ + int pins ; + char *ipAddress, *port, *password ; + char pPort [1024] ; + + if ((params = extractInt (progName, params, &pins)) == NULL) + return FALSE ; + + if ((pins < 1) || (pins > 1000)) + { + verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ; + return FALSE ; + } + + if ((params = extractStr (progName, params, &ipAddress)) == NULL) + return FALSE ; + + if (strlen (ipAddress) == 0) + { + verbError ("%s: ipAddress required", progName) ; + return FALSE ; + } + + if ((params = extractStr (progName, params, &port)) == NULL) + return FALSE ; + + if (strlen (port) == 0) + { + sprintf (pPort, "%d", DEFAULT_SERVER_PORT) ; + port = pPort ; + } + + if ((params = extractStr (progName, params, &password)) == NULL) + return FALSE ; + + if (strlen (password) == 0) + { + verbError ("%s: password required", progName) ; + return FALSE ; + } + + return drcSetupNet (pinBase, pins, ipAddress, port, password) ; +} + + + +/* + * Function list + ********************************************************************************* + */ + +static struct extensionFunctionStruct extensionFunctions [] = +{ + { "mcp23008", &doExtensionMcp23008 }, + { "mcp23016", &doExtensionMcp23016 }, + { "mcp23017", &doExtensionMcp23017 }, + { "mcp23s08", &doExtensionMcp23s08 }, + { "mcp23s17", &doExtensionMcp23s17 }, + { "sr595", &doExtensionSr595 }, + { "pcf8574", &doExtensionPcf8574 }, + { "pcf8591", &doExtensionPcf8591 }, + { "bmp180", &doExtensionBmp180 }, + { "pseudoPins", &doExtensionPseudoPins }, + { "htu21d", &doExtensionHtu21d }, + { "ds18b20", &doExtensionDs18b20 }, + { "rht03", &doExtensionRht03 }, + { "mcp3002", &doExtensionMcp3002 }, + { "mcp3004", &doExtensionMcp3004 }, + { "mcp4802", &doExtensionMcp4802 }, + { "mcp3422", &doExtensionMcp3422 }, + { "max31855", &doExtensionMax31855 }, + { "ads1115", &doExtensionAds1115 }, + { "max5322", &doExtensionMax5322 }, + { "sn3218", &doExtensionSn3218 }, + { "drcs", &doExtensionDrcS }, + { "drcn", &doExtensionDrcNet }, + { NULL, NULL }, +} ; + + +/* + * loadWPiExtension: + * Load in a wiringPi extension + * The extensionData always starts with the name, a colon then the pinBase + * number. Other parameters after that are decoded by the module in question. + ********************************************************************************* + */ + +int loadWPiExtension (char *progName, char *extensionData, int printErrors) +{ + char *p ; + char *extension = extensionData ; + struct extensionFunctionStruct *extensionFn ; + int pinBase = 0 ; + + verbose = printErrors ; + +// Get the extension name by finding the first colon + + p = extension ; + while (*p != ':') + { + if (!*p) // ran out of characters + { + verbError ("%s: extension name not terminated by a colon", progName) ; + return FALSE ; + } + ++p ; + } + *p++ = 0 ; + +// Simple ATOI code + + if (!isdigit (*p)) + { + verbError ("%s: decimal pinBase number expected after extension name", progName) ; + return FALSE ; + } + + while (isdigit (*p)) + { + if (pinBase > 2147483647) // 2^31-1 ... Lets be realistic here... + { + verbError ("%s: pinBase too large", progName) ; + return FALSE ; + } + + pinBase = pinBase * 10 + (*p - '0') ; + ++p ; + } + + if (pinBase < 64) + { + verbError ("%s: pinBase (%d) too small. Minimum is 64.", progName, pinBase) ; + return FALSE ; + } + +// Search for extensions: + + for (extensionFn = extensionFunctions ; extensionFn->name != NULL ; ++extensionFn) + { + if (strcmp (extensionFn->name, extension) == 0) + return extensionFn->function (progName, pinBase, p) ; + } + + fprintf (stderr, "%s: extension %s not found", progName, extension) ; + return FALSE ; +} diff --git a/wiringPi/wpiExtensions.h b/wiringPi/wpiExtensions.h new file mode 100644 index 0000000..fcaec96 --- /dev/null +++ b/wiringPi/wpiExtensions.h @@ -0,0 +1,26 @@ +/* + * extensions.h: + * Part of the GPIO program to test, peek, poke and otherwise + * noodle with the GPIO hardware on the Raspberry Pi. + * Copyright (c) 2012-2015 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + + +extern int loadWPiExtension (char *progName, char *extensionData, int verbose) ; diff --git a/wiringPiD/Makefile b/wiringPiD/Makefile new file mode 100644 index 0000000..6b2cc9e --- /dev/null +++ b/wiringPiD/Makefile @@ -0,0 +1,100 @@ +# +# Makefile: +# The wiringPiD utility: +# https://projects.drogon.net/wiring-pi +# +# Copyright (c) 2012-2017 Gordon Henderson +################################################################################# +# This file is part of wiringPi: +# A "wiring" library for the Raspberry Pi +# +# wiringPi is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# wiringPi is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with wiringPi. If not, see . +################################################################################# + +DESTDIR?=/usr +PREFIX?=/local + +ifneq ($V,1) +Q ?= @ +endif + +#DEBUG = -g -O0 +DEBUG = -O2 +CC = gcc +INCLUDE = -I$(DESTDIR)$(PREFIX)/include +CFLAGS = $(DEBUG) -Wall -Wextra $(INCLUDE) -Winline -pipe + +LDFLAGS = -L$(DESTDIR)$(PREFIX)/lib +LIBS = -lwiringPi -lwiringPiDev -lpthread -lrt -lm -lcrypt + +# May not need to alter anything below this line +############################################################################### + +SRC = wiringpid.c network.c runRemote.c daemonise.c + +OBJ = $(SRC:.c=.o) + +all: wiringpid + +wiringpid: $(OBJ) + $Q echo [Link] + $Q $(CC) -o $@ $(OBJ) $(LDFLAGS) $(LIBS) + +.c.o: + $Q echo [Compile] $< + $Q $(CC) -c $(CFLAGS) $< -o $@ + +.PHONY: clean +clean: + $Q echo "[Clean]" + $Q rm -f $(OBJ) wiringpid *~ core tags *.bak + +.PHONY: tags +tags: $(SRC) + $Q echo [ctags] + $Q ctags $(SRC) + +.PHONY: install +install: wiringpid + $Q echo "[Install]" + $Q mkdir -p $(DESTDIR)$(PREFIX)/sbin + $Q cp wiringpid $(DESTDIR)$(PREFIX)/sbin + $Q chown root.root $(DESTDIR)$(PREFIX)/sbin/wiringpid + +# $Q mkdir -p $(DESTDIR)$(PREFIX)/man/man8 +# $Q cp gpio.1 $(DESTDIR)$(PREFIX)/man/man8 + +.PHONY: install-deb +install-deb: gpio + $Q echo "[Install: deb]" + $Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/usr/bin + $Q install -m 0755 gpio ~/wiringPi/debian-template/wiringPi/usr/bin + $Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/man/man1 + $Q install -m 0644 gpio.1 ~/wiringPi/debian-template/wiringPi/man/man1 + +.PHONY: uninstall +uninstall: + $Q echo "[UnInstall]" + $Q rm -f $(DESTDIR)$(PREFIX)/sbin/wiringpid + $Q rm -f $(DESTDIR)$(PREFIX)/man/man8/wiringpid.8 + +.PHONY: depend +depend: + makedepend -Y $(SRC) +# DO NOT DELETE + +wiringpid.o: drcNetCmd.h network.h runRemote.h daemonise.h +network.o: network.h +runRemote.o: drcNetCmd.h network.h runRemote.h +daemonise.o: daemonise.h diff --git a/wiringPiD/daemonise.c b/wiringPiD/daemonise.c new file mode 100644 index 0000000..134a6bb --- /dev/null +++ b/wiringPiD/daemonise.c @@ -0,0 +1,82 @@ +/* + * daemonise.c: + * Fairly generic "Turn the current process into a daemon" code. + * + * Copyright (c) 2016-2017 Gordon Henderson. + ********************************************************************************* + */ + +#include +#include +#include +#include +#include +#include + +#include "daemonise.h" + +void daemonise (const char *pidFile) +{ + pid_t pid ; + int i ; + FILE *fd ; + + syslog (LOG_DAEMON | LOG_INFO, "Becoming daemon") ; + +// Fork from the parent + + if ((pid = fork ()) < 0) + { + syslog (LOG_DAEMON | LOG_ALERT, "Fork no. 1 failed: %m") ; + exit (EXIT_FAILURE) ; + } + + if (pid > 0) // Parent - terminate + exit (EXIT_SUCCESS) ; + +// Now running on the child - become session leader + + if (setsid() < 0) + { + syslog (LOG_DAEMON | LOG_ALERT, "setsid failed: %m") ; + exit (EXIT_FAILURE) ; + } + +// Ignore a few signals + + signal (SIGCHLD, SIG_IGN) ; + signal (SIGHUP, SIG_IGN) ; + +// Fork again + + if ((pid = fork ()) < 0) + { + syslog (LOG_DAEMON | LOG_ALERT, "Fork no. 2 failed: %m") ; + exit (EXIT_FAILURE) ; + } + + if (pid > 0) // parent - terminate + exit (EXIT_SUCCESS) ; + +// Tidying up - reset umask, change to / and close all files + + umask (0) ; + chdir ("/") ; + + for (i = 0 ; i < sysconf (_SC_OPEN_MAX) ; ++i) + close (i) ; + +// Write PID into /var/run + + if (pidFile != NULL) + { + if ((fd = fopen (pidFile, "w")) == NULL) + { + syslog (LOG_DAEMON | LOG_ALERT, "Unable to write PID file: %m") ; + exit (EXIT_FAILURE) ; + } + + fprintf (fd, "%d\n", getpid ()) ; + fclose (fd) ; + } +} diff --git a/wiringPiD/daemonise.h b/wiringPiD/daemonise.h new file mode 100644 index 0000000..8d13319 --- /dev/null +++ b/wiringPiD/daemonise.h @@ -0,0 +1,9 @@ +/* + * daemonise.h: + * Fairly generic "Turn the current process into a daemon" code. + * + * Copyright (c) 2016-2017 Gordon Henderson. + ********************************************************************************* + */ + +extern void daemonise (const char *pidFile) ; diff --git a/wiringPiD/drcNetCmd.h b/wiringPiD/drcNetCmd.h new file mode 100644 index 0000000..23f7dc1 --- /dev/null +++ b/wiringPiD/drcNetCmd.h @@ -0,0 +1,44 @@ +/* + * drcNetCmd.c: + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#define DEFAULT_SERVER_PORT 6124 + +#define DRCN_PIN_MODE 1 +#define DRCN_PULL_UP_DN 2 + +#define DRCN_DIGITAL_WRITE 3 +#define DRCN_DIGITAL_WRITE8 4 +#define DRCN_ANALOG_WRITE 5 +#define DRCN_PWM_WRITE 6 + +#define DRCN_DIGITAL_READ 7 +#define DRCN_DIGITAL_READ8 8 +#define DRCN_ANALOG_READ 9 + + +struct drcNetComStruct +{ + uint32_t pin ; + uint32_t cmd ; + uint32_t data ; +} comDat ; + diff --git a/wiringPiD/network.c b/wiringPiD/network.c new file mode 100644 index 0000000..9f6bb88 --- /dev/null +++ b/wiringPiD/network.c @@ -0,0 +1,330 @@ +/* + * network.c: + * Part of wiringPiD + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "network.h" + +#define TRUE (1==1) +#define FALSE (!TRUE) + +// Local data + +#define SALT_LEN 16 + +static char salt [SALT_LEN + 1] ; +static char *returnedHash = NULL ; +static int serverFd = -1 ; + +// Union for the server Socket Address + +static union +{ + struct sockaddr_in sin ; + struct sockaddr_in6 sin6 ; +} serverSockAddr ; + +// and client address + +static union +{ + struct sockaddr_in sin ; + struct sockaddr_in6 sin6 ; +} clientSockAddr ; + + +/* + * getClientIP: + * Returns a pointer to a static string containing the clients IP address + ********************************************************************************* + */ + +char *getClientIP (void) +{ + char buf [INET6_ADDRSTRLEN] ; + static char ipAddress [1024] ; + + if (clientSockAddr.sin.sin_family == AF_INET) // IPv4 + { + if (snprintf (ipAddress, 1024, "IPv4: %s", + inet_ntop (clientSockAddr.sin.sin_family, (void *)&clientSockAddr.sin.sin_addr, buf, sizeof (buf))) == 1024) + strcpy (ipAddress, "Too long") ; + } + else // IPv6 + { + if (clientSockAddr.sin.sin_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED (&clientSockAddr.sin6.sin6_addr)) + { + if (snprintf (ipAddress, 1024, "IPv4in6: %s", + inet_ntop (clientSockAddr.sin.sin_family, (char *)&clientSockAddr.sin6.sin6_addr, buf, sizeof(buf))) == 1024) + strcpy (ipAddress, "Too long") ; + } + else + { + if (snprintf (ipAddress, 1024, "IPv6: %s", + inet_ntop (clientSockAddr.sin.sin_family, (char *)&clientSockAddr.sin6.sin6_addr, buf, sizeof(buf))) == 1024) + strcpy (ipAddress, "Too long") ; + } + } + + return ipAddress ; +} + + + +/* + * clientPstr: clientPrintf: + * Print over a network socket + ********************************************************************************* + */ + +static int clientPstr (int fd, char *s) +{ + int len = strlen (s) ; + return (write (fd, s, len) == len) ? 0 : -1 ; +} + +static int clientPrintf (const int fd, const char *message, ...) +{ + va_list argp ; + char buffer [1024] ; + + va_start (argp, message) ; + vsnprintf (buffer, 1023, message, argp) ; + va_end (argp) ; + + return clientPstr (fd, buffer) ; +} + + +/* + * sendGreeting: + * Send some text to the client device + ********************************************************************************* + */ + +int sendGreeting (int clientFd) +{ + if (clientPrintf (clientFd, "200 Welcome to wiringPiD - http://wiringpi.com/\n") < 0) + return -1 ; + + return clientPrintf (clientFd, "200 Connecting from: %s\n", getClientIP ()) ; +} + + +/* + * getSalt: + * Create a random 'salt' value for the password encryption process + ********************************************************************************* + */ + +static int getSalt (char drySalt []) +{ + static const char *seaDog = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789/." ; + + unsigned char wetSalt [SALT_LEN] ; + int i, fd ; + + if ((fd = open ("/dev/urandom", O_RDONLY)) < 0) + return fd ; + + if (read (fd, wetSalt, SALT_LEN) != SALT_LEN) + return -1 ; + + close (fd) ; + + for (i = 0 ; i < SALT_LEN ; ++i) + drySalt [i] = seaDog [wetSalt [i] & 63] ; + + drySalt [SALT_LEN] = 0 ; + + return 0 ; +} + + +/* + * sendChallenge: + * Create and send our salt (aka nonce) to the remote device + ********************************************************************************* + */ + +int sendChallenge (int clientFd) +{ + if (getSalt (salt) < 0) + return -1 ; + + return clientPrintf (clientFd, "Challenge %s\n", salt) ; +} + + +/* + * getResponse: + * Read the encrypted password from the remote device. + ********************************************************************************* + */ + + +int getResponse (int clientFd) +{ + char reply [1024] ; + int len ; + +// Being sort of lazy about this. I'm expecting an SHA-512 hash back and these +// are exactly 86 characters long, so no reason not to, I guess... + + len = 86 ; + + if (setsockopt (clientFd, SOL_SOCKET, SO_RCVLOWAT, (void *)&len, sizeof (len)) < 0) + return -1 ; + + len = recv (clientFd, reply, 86, 0) ; + if (len != 86) + return -1 ; + + reply [len] = 0 ; + + if ((returnedHash = malloc (len + 1)) == NULL) + return -1 ; + + strcpy (returnedHash, reply) ; + + return 0 ; +} + + +/* + * passwordMatch: + * See if there's a match. If not, we simply dump them. + ********************************************************************************* + */ + +int passwordMatch (const char *password) +{ + char *encrypted ; + char salted [1024] ; + + sprintf (salted, "$6$%s$", salt) ; + + encrypted = crypt (password, salted) ; + +// 20: $6$ then 16 characters of salt, then $ +// 86 is the length of an SHA-512 hash + + return strncmp (encrypted + 20, returnedHash, 86) == 0 ; +} + + +/* + * setupServer: + * Do what's needed to create a local server socket instance that can listen + * on both IPv4 and IPv6 interfaces. + ********************************************************************************* + */ + +int setupServer (int serverPort) +{ + socklen_t clientSockAddrSize = sizeof (clientSockAddr) ; + + int on = 1 ; + int family ; + socklen_t serverSockAddrSize ; + int clientFd ; + +// Try to create an IPv6 socket + + serverFd = socket (PF_INET6, SOCK_STREAM, 0) ; + +// If it didn't work, then fall-back to IPv4. + + if (serverFd < 0) + { + if ((serverFd = socket (PF_INET, SOCK_STREAM, 0)) < 0) + return -1 ; + + family = AF_INET ; + serverSockAddrSize = sizeof (struct sockaddr_in) ; + } + else // We got an IPv6 socket + { + family = AF_INET6 ; + serverSockAddrSize = sizeof (struct sockaddr_in6) ; + } + + if (setsockopt (serverFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) + return -1 ; + +// Setup the servers socket address - cope with IPv4 and v6. + + memset (&serverSockAddr, 0, sizeof (serverSockAddr)) ; + switch (family) + { + case AF_INET: + serverSockAddr.sin.sin_family = AF_INET ; + serverSockAddr.sin.sin_addr.s_addr = htonl (INADDR_ANY) ; + serverSockAddr.sin.sin_port = htons (serverPort) ; + break; + + case AF_INET6: + serverSockAddr.sin6.sin6_family = AF_INET6 ; + serverSockAddr.sin6.sin6_addr = in6addr_any ; + serverSockAddr.sin6.sin6_port = htons (serverPort) ; + } + +// Bind, listen and accept + + if (bind (serverFd, (struct sockaddr *)&serverSockAddr, serverSockAddrSize) < 0) + return -1 ; + + if (listen (serverFd, 4) < 0) // Really only going to talk to one client at a time... + return -1 ; + + if ((clientFd = accept (serverFd, (struct sockaddr *)&clientSockAddr, &clientSockAddrSize)) < 0) + return -1 ; + + return clientFd ; +} + + +/* + * closeServer: + ********************************************************************************* + */ + +void closeServer (int clientFd) +{ + if (serverFd != -1) close (serverFd) ; + if (clientFd != -1) close (clientFd) ; + serverFd = clientFd = -1 ; +} diff --git a/wiringPiD/network.h b/wiringPiD/network.h new file mode 100644 index 0000000..94c3380 --- /dev/null +++ b/wiringPiD/network.h @@ -0,0 +1,31 @@ +/* + * network.h: + * Part of wiringPiD + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +extern char *getClientIP (void) ; +extern int getResponce (int clientFd) ; +extern int setupServer (int serverPort) ; +extern int sendGreeting (int clientFd) ; +extern int sendChallenge (int clientFd) ; +extern int getResponse (int clientFd) ; +extern int passwordMatch (const char *password) ; +extern void closeServer (int clientFd) ; diff --git a/wiringPiD/runRemote.c b/wiringPiD/runRemote.c new file mode 100644 index 0000000..cd7432b --- /dev/null +++ b/wiringPiD/runRemote.c @@ -0,0 +1,126 @@ +/* + * runRemote.c: + * Run the remote commands passed over the network link. + * + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +//#include + +#include +#include + +#include "drcNetCmd.h" +#include "network.h" +#include "runRemote.h" + + + +int noLocalPins = FALSE ; + + +void runRemoteCommands (int fd) +{ + register uint32_t pin ; + int len ; + struct drcNetComStruct cmd ; + + len = sizeof (struct drcNetComStruct) ; + + if (setsockopt (fd, SOL_SOCKET, SO_RCVLOWAT, (void *)&len, sizeof (len)) < 0) + return ; + + for (;;) + { + if (recv (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) // Probably remote hangup + return ; + + pin = cmd.pin ; + if (noLocalPins && ((pin & PI_GPIO_MASK) == 0)) + { + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + continue ; + } + + switch (cmd.cmd) + { + case DRCN_PIN_MODE: + pinMode (pin, cmd.data) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_PULL_UP_DN: + pullUpDnControl (pin, cmd.data) ; + break ; + + case DRCN_PWM_WRITE: + pwmWrite (pin, cmd.data) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_DIGITAL_WRITE: + digitalWrite (pin, cmd.data) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_DIGITAL_WRITE8: + //digitalWrite8 (pin, cmd.data) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_DIGITAL_READ: + cmd.data = digitalRead (pin) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_DIGITAL_READ8: + //cmd.data = digitalRead8 (pin) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_ANALOG_WRITE: + analogWrite (pin, cmd.data) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + + case DRCN_ANALOG_READ: + cmd.data = analogRead (pin) ; + if (send (fd, &cmd, sizeof (cmd), 0) != sizeof (cmd)) + return ; + break ; + } + } + +} diff --git a/wiringPiD/runRemote.h b/wiringPiD/runRemote.h new file mode 100644 index 0000000..57d5018 --- /dev/null +++ b/wiringPiD/runRemote.h @@ -0,0 +1,29 @@ +/* + * runRemote.h: + * Run the remote commands passed over the network link. + * + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +// Globals + +extern int noLocalPins ; + +extern void runRemoteCommands (int fd) ; diff --git a/wiringPiD/wiringpid.c b/wiringPiD/wiringpid.c new file mode 100644 index 0000000..8dde1cd --- /dev/null +++ b/wiringPiD/wiringpid.c @@ -0,0 +1,382 @@ +/* + * wiringPiD.c: + * Copyright (c) 2012-2017 Gordon Henderson + *********************************************************************** + * This file is part of wiringPi: + * https://projects.drogon.net/raspberry-pi/wiringpi/ + * + * wiringPi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wiringPi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with wiringPi. If not, see . + *********************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "drcNetCmd.h" +#include "network.h" +#include "runRemote.h" +#include "daemonise.h" + + +#define PIDFILE "/var/run/wiringPiD.pid" + + +// Globals + +static const char *usage = "[-h] [-d] [-g | -1 | -z] [[-x extension:pin:params] ...] password" ; +static int doDaemon = FALSE ; + +// + +static void logMsg (const char *message, ...) +{ + va_list argp ; + char buffer [1024] ; + + va_start (argp, message) ; + vsnprintf (buffer, 1023, message, argp) ; + va_end (argp) ; + + if (doDaemon) + syslog (LOG_DAEMON | LOG_INFO, "%s", buffer) ; + else + printf ("%s\n", buffer) ; +} + + +/* + * sigHandler: + * setupSigHandler: + * Somehing has happened that would normally terminate the program so try + * to close down nicely. + ********************************************************************************* + */ + +void sigHandler (int sig) +{ + logMsg ("Exiting on signal %d: %s", sig, strsignal (sig)) ; + (void)unlink (PIDFILE) ; + exit (EXIT_FAILURE) ; +} + +void setupSigHandler (void) +{ + struct sigaction action ; + + sigemptyset (&action.sa_mask) ; + action.sa_flags = 0 ; + +// Ignore what we can + + action.sa_handler = SIG_IGN ; + + sigaction (SIGHUP, &action, NULL) ; + sigaction (SIGTTIN, &action, NULL) ; + sigaction (SIGTTOU, &action, NULL) ; + +// Trap what we can to exit gracefully + + action.sa_handler = sigHandler ; + + sigaction (SIGINT, &action, NULL) ; + sigaction (SIGQUIT, &action, NULL) ; + sigaction (SIGILL, &action, NULL) ; + sigaction (SIGABRT, &action, NULL) ; + sigaction (SIGFPE, &action, NULL) ; + sigaction (SIGSEGV, &action, NULL) ; + sigaction (SIGPIPE, &action, NULL) ; + sigaction (SIGALRM, &action, NULL) ; + sigaction (SIGTERM, &action, NULL) ; + sigaction (SIGUSR1, &action, NULL) ; + sigaction (SIGUSR2, &action, NULL) ; + sigaction (SIGCHLD, &action, NULL) ; + sigaction (SIGTSTP, &action, NULL) ; + sigaction (SIGBUS, &action, NULL) ; +} + + +/* + * The works... + ********************************************************************************* + */ + +int main (int argc, char *argv []) +{ + int clientFd ; + char *p, *password ; + int i ; + int port = DEFAULT_SERVER_PORT ; + int wpiSetup = 0 ; + + if (argc < 2) + { + fprintf (stderr, "Usage: %s %s\n", argv [0], usage) ; + exit (EXIT_FAILURE) ; + } + +// Help? + + if (strcasecmp (argv [1], "-h") == 0) + { + printf ("Usage: %s %s\n", argv [0], usage) ; + return 0 ; + } + +// Daemonize? +// Must come before the other args as e.g. some extensions +// open files which get closed on daemonise... + + if (strcasecmp (argv [1], "-d") == 0) + { + if (geteuid () != 0) + { + fprintf (stderr, "%s: Must be root to run as a daemon.\n", argv [0]) ; + exit (EXIT_FAILURE) ; + } + + doDaemon = TRUE ; + daemonise (PIDFILE) ; + + for (i = 2 ; i < argc ; ++i) + argv [i - 1] = argv [i] ; + --argc ; + } + +// Scan all other arguments + + while (*argv [1] == '-') + { + +// Look for wiringPi setup arguments: +// Same as the gpio command and rtb. + +// -g - bcm_gpio + + if (strcasecmp (argv [1], "-g") == 0) + { + if (wpiSetup == 0) + { + logMsg ("BCM_GPIO mode selected") ; + wiringPiSetupGpio () ; + } + + for (i = 2 ; i < argc ; ++i) + argv [i - 1] = argv [i] ; + --argc ; + ++wpiSetup ; + continue ; + } + +// -1 - physical pins + + if (strcasecmp (argv [1], "-1") == 0) + { + if (wpiSetup == 0) + { + logMsg ("GPIO-PHYS mode selected") ; + wiringPiSetupPhys () ; + } + + for (i = 2 ; i < argc ; ++i) + argv [i - 1] = argv [i] ; + --argc ; + ++wpiSetup ; + continue ; + } + +// -z - no wiringPi - blocks remotes accessing local pins + + if (strcasecmp (argv [1], "-z") == 0) + { + if (wpiSetup == 0) + logMsg ("No GPIO mode selected") ; + + for (i = 2 ; i < argc ; ++i) + argv [i - 1] = argv [i] ; + --argc ; + noLocalPins = TRUE ; + ++wpiSetup ; + continue ; + } + +// -p to select the port + + if (strcasecmp (argv [1], "-p") == 0) + { + if (argc < 3) + { + logMsg ("-p missing extension port") ; + exit (EXIT_FAILURE) ; + } + + logMsg ("Setting port to: %s", argv [2]) ; + + port = atoi (argv [2]) ; + if ((port < 1) || (port > 65535)) + { + logMsg ("Invalid server port: %d", port) ; + exit (EXIT_FAILURE) ; + } + +// Shift args down by 2 + + for (i = 3 ; i < argc ; ++i) + argv [i - 2] = argv [i] ; + argc -= 2 ; + + continue ; + } + +// Check for -x argument to load in a new extension +// -x extension:base:args +// Can load many modules to extend the daemon. + + if (strcasecmp (argv [1], "-x") == 0) + { + if (argc < 3) + { + logMsg ("-x missing extension name:data:etc.") ; + exit (EXIT_FAILURE) ; + } + + logMsg ("Loading extension: %s", argv [2]) ; + + if (!loadWPiExtension (argv [0], argv [2], TRUE)) + { + logMsg ("Extension load failed: %s", strerror (errno)) ; + exit (EXIT_FAILURE) ; + } + +// Shift args down by 2 + + for (i = 3 ; i < argc ; ++i) + argv [i - 2] = argv [i] ; + argc -= 2 ; + + continue ; + } + + logMsg ("Invalid parameter: %s", argv [1]) ; + exit (EXIT_FAILURE) ; + } + +// Default to wiringPi mode + + if (wpiSetup == 0) + { + logMsg ("WiringPi GPIO mode selected") ; + wiringPiSetup () ; + } + +// Finally, should just be one arg left - the password... + + if (argc != 2) + { + logMsg ("No password supplied") ; + exit (EXIT_FAILURE) ; + } + + if (strlen (argv [1]) < 6) + { + logMsg ("Password too short - at least 6 chars, not %d", strlen (argv [1])) ; + exit (EXIT_FAILURE) ; + } + + if ((password = malloc (strlen (argv [1]) + 1)) == NULL) + { + logMsg ("Out of memory") ; + exit (EXIT_FAILURE) ; + } + strcpy (password, argv [1]) ; + +// Wipe out the password on the command-line in a vague attempt to try to +// hide it from snoopers + + for (p = argv [1] ; *p ; ++p) + *p = ' ' ; + + setupSigHandler () ; + +// Enter our big loop + + for (;;) + { + + if (!doDaemon) + printf ("-=-\nWaiting for a new connection...\n") ; + + if ((clientFd = setupServer (port)) < 0) + { + logMsg ("Unable to setup server: %s", strerror (errno)) ; + exit (EXIT_FAILURE) ; + } + + logMsg ("New connection from: %s.", getClientIP ()) ; + + if (!doDaemon) + printf ("Sending Greeting.\n") ; + + if (sendGreeting (clientFd) < 0) + { + logMsg ("Unable to send greeting message: %s", strerror (errno)) ; + closeServer (clientFd) ; + continue ; + } + + if (!doDaemon) + printf ("Sending Challenge.\n") ; + + if (sendChallenge (clientFd) < 0) + { + logMsg ("Unable to send challenge message: %s", strerror (errno)) ; + closeServer (clientFd) ; + continue ; + } + + if (!doDaemon) + printf ("Waiting for response.\n") ; + + if (getResponse (clientFd) < 0) + { + logMsg ("Connection closed waiting for response: %s", strerror (errno)) ; + closeServer (clientFd) ; + continue ; + } + + if (!passwordMatch (password)) + { + logMsg ("Password failure") ; + closeServer (clientFd) ; + continue ; + } + + logMsg ("Password OK - Starting") ; + + runRemoteCommands (clientFd) ; + closeServer (clientFd) ; + } + + return 0 ; +}