diff --git a/.gitignore b/.gitignore index 9eca6c8..ed2ec80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ -*.a *.o +*.so +lib*.so.* +*~ +debian-template/wiringPi +debian-template/wiringpi-*.deb +gpio/gpio diff --git a/VERSION b/VERSION index 3125d73..0f34dc7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.31 +2.32 diff --git a/build b/build index c2a589c..368e8f4 100755 --- a/build +++ b/build @@ -62,6 +62,8 @@ if [ x$1 = "xclean" ]; then echo -n "Quick2Wire: " ; make clean cd ../PiGlow echo -n "PiGlow: " ; make clean + cd ../scrollPhat + echo -n "scrollPhat: " ; make clean exit fi diff --git a/debian-template/wiringPi/DEBIAN/control b/debian-template/wiringPi/DEBIAN/control index 5d698c8..230da07 100644 --- a/debian-template/wiringPi/DEBIAN/control +++ b/debian-template/wiringPi/DEBIAN/control @@ -1,5 +1,5 @@ Package: wiringpi -Version: 2.31 +Version: 2.32 Section: libraries Priority: optional Architecture: armhf diff --git a/devLib/Makefile b/devLib/Makefile index 0fb0033..1b1ebe0 100644 --- a/devLib/Makefile +++ b/devLib/Makefile @@ -48,11 +48,13 @@ LIBS = SRC = ds1302.c maxdetect.c piNes.c \ gertboard.c piFace.c \ lcd128x64.c lcd.c \ + scrollPhat.c \ piGlow.c OBJ = $(SRC:.c=.o) -HEADERS = ds1302.h gertboard.h lcd128x64.h lcd.h maxdetect.h piFace.h piGlow.h piNes.h +HEADERS = ds1302.h gertboard.h lcd128x64.h lcd.h maxdetect.h piFace.h piGlow.h piNes.h\ + scrollPhat.h all: $(DYNAMIC) @@ -134,4 +136,5 @@ gertboard.o: gertboard.h piFace.o: piFace.h lcd128x64.o: font.h lcd128x64.h lcd.o: lcd.h +scrollPhat.o: scrollPhatFont.h scrollPhat.h piGlow.o: piGlow.h diff --git a/devLib/maxdetect.c b/devLib/maxdetect.c index 23eabf8..74ff70e 100644 --- a/devLib/maxdetect.c +++ b/devLib/maxdetect.c @@ -22,7 +22,8 @@ *********************************************************************** */ -//#include +#include +#include //#include //#include @@ -38,21 +39,43 @@ /* * maxDetectLowHighWait: - * Wait for a transition from high to low on the bus + * Wait for a transition from low to high on the bus ********************************************************************************* */ -static void maxDetectLowHighWait (const int pin) +static int maxDetectLowHighWait (const int pin) { - unsigned int timeOut = millis () + 2000 ; + 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) - if (millis () > timeOut) - return ; + { + 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) - if (millis () > timeOut) - return ; + { + gettimeofday (&now, NULL) ; + if (timercmp (&now, &timeUp, >)) + return FALSE ; + } + + return TRUE ; } @@ -69,7 +92,8 @@ static unsigned int maxDetectClockByte (const int pin) for (bit = 0 ; bit < 8 ; ++bit) { - maxDetectLowHighWait (pin) ; + if (!maxDetectLowHighWait (pin)) + return 0 ; // bit starting now - we need to time it. @@ -95,6 +119,11 @@ 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. @@ -106,7 +135,8 @@ int maxDetectRead (const int pin, unsigned char buffer [4]) // Now wait for sensor to pull pin low - maxDetectLowHighWait (pin) ; + if (!maxDetectLowHighWait (pin)) + return FALSE ; // and read in 5 bytes (40 bits) @@ -121,6 +151,22 @@ int maxDetectRead (const int pin, unsigned char buffer [4]) } 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] ; } @@ -128,38 +174,65 @@ int maxDetectRead (const int pin, unsigned char buffer [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 unsigned int nextTime = 0 ; - static int lastTemp = 0 ; - static int lastRh = 0 ; - static int lastResult = TRUE ; + 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] ; -// Don't read more than once a second +// The data sheets say to not read more than once every 2 seconds, so you +// get the last good reading - if (millis () < nextTime) + gettimeofday (&now, NULL) ; + if (timercmp (&now, &then, <)) { - *temp = lastTemp ; *rh = lastRh ; - return lastResult ; - } - - lastResult = maxDetectRead (pin, buffer) ; - - if (lastResult) - { - *temp = lastTemp = (buffer [2] * 256 + buffer [3]) ; - *rh = lastRh = (buffer [0] * 256 + buffer [1]) ; - nextTime = millis () + 2000 ; + *temp = lastTemp ; return TRUE ; } - else - { + +// 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/piFaceOld.c b/devLib/piFaceOld.c new file mode 100644 index 0000000..1b1c0dd --- /dev/null +++ b/devLib/piFaceOld.c @@ -0,0 +1,178 @@ +/* + * piFace.: + * Arduino compatable (ish) Wiring library for the Raspberry Pi + * Copyright (c) 2012-2013 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/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/rht03.c b/examples/rht03.c index 566e954..854f837 100644 --- a/examples/rht03.c +++ b/examples/rht03.c @@ -27,7 +27,7 @@ #include #include -#define RHT03_PIN 0 +#define RHT03_PIN 7 /* *********************************************************************** @@ -37,32 +37,49 @@ int main (void) { - int temp, rh ; - int newTemp, newRh ; + int result, temp, rh ; + int minT, maxT, minRH, maxRH ; - temp = rh = newTemp = newRh = 0 ; + int numGood, numBad ; wiringPiSetup () ; piHiPri (55) ; + minT = 1000 ; + maxT = -1000 ; + + minRH = 1000 ; + maxRH = -1000 ; + + numGood = numBad = 0 ; + for (;;) { delay (100) ; - if (!readRHT03 (RHT03_PIN, &newTemp, &newRh)) - continue ; + result = readRHT03 (RHT03_PIN, &temp, &rh) ; - if ((temp != newTemp) || (rh != newRh)) + if (!result) { - temp = newTemp ; - rh = newRh ; - if ((temp & 0x8000) != 0) // Negative - { - temp &= 0x7FFF ; - temp = -temp ; - } - printf ("Temp: %5.1f, RH: %5.1f%%\n", temp / 10.0, rh / 10.0) ; + 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..c0b7241 --- /dev/null +++ b/examples/scrollPhat/Makefile @@ -0,0 +1,79 @@ +# +# Makefile: +# wiringPi - Wiring Compatable library for the Raspberry Pi +# https://projects.drogon.net/wiring-pi +# +# Copyright (c) 2012-2015 Gordon Henderson +################################################################################# +# This file is part of wiringPi: +# Wiring Compatable 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/gpio.c b/gpio/gpio.c index 6c95b21..6162090 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -47,6 +47,7 @@ extern int wiringPiDebug ; // External functions I can't be bothered creating a separate .h file for: extern void doReadall (void) ; +extern void doAllReadall (void) ; extern void doPins (void) ; #ifndef TRUE @@ -115,10 +116,12 @@ static void changeOwner (char *cmd, char *file) if (chown (file, uid, gid) != 0) { - if (errno == ENOENT) // Warn that it's not there - fprintf (stderr, "%s: Warning (not an error, do not report): File not present: %s\n", cmd, file) ; - else - fprintf (stderr, "%s: Warning (not an error): Unable to change ownership of %s: %s\n", cmd, file, strerror (errno)) ; + +// Removed (ignoring) the check for not existing as I'm fed-up with morons telling me that +// the warning message is an error. + + if (errno != ENOENT) + fprintf (stderr, "%s: Unable to change ownership of %s: %s\n", cmd, file, strerror (errno)) ; } } @@ -138,7 +141,7 @@ static int moduleLoaded (char *modName) if (fd == NULL) { - fprintf (stderr, "gpio: Unable to check modules: %s\n", strerror (errno)) ; + fprintf (stderr, "gpio: Unable to check /proc/modules: %s\n", strerror (errno)) ; exit (1) ; } @@ -774,13 +777,13 @@ static void doUsbP (int argc, char *argv []) piBoardId (&model, &rev, &mem, &maker, &overVolted) ; - if (model != PI_MODEL_BP) + if (!((model == PI_MODEL_BP) || (model == PI_MODEL_2))) { - fprintf (stderr, "USB power contol is applicable to B+ boards only.\n") ; + fprintf (stderr, "USB power contol is applicable to B+ and v2 boards only.\n") ; exit (1) ; } -// Need to force BCM_GPIO mode: +// Make sure we start in BCM_GPIO mode wiringPiSetupGpio () ; @@ -1150,7 +1153,8 @@ static void doPwmClock (int argc, char *argv []) /* * doVersion: - * Handle the ever more complicated version command + * Handle the ever more complicated version command and print out + * some usefull information. ********************************************************************************* */ @@ -1166,35 +1170,23 @@ static void doVersion (char *argv []) printf ("\n") ; piBoardId (&model, &rev, &mem, &maker, &warranty) ; -/************* - if (model == PI_MODEL_UNKNOWN) - { - printf ("Your Raspberry Pi has an unknown model type. Please report this to\n") ; - printf (" projects@drogon.net\n") ; - printf ("with a copy of your /proc/cpuinfo if possible\n") ; - } - else -***************/ - - { - printf ("Raspberry Pi Details:\n") ; - printf (" Type: %s, Revision: %s, Memory: %dMB, Maker: %s %s\n", - piModelNames [model], piRevisionNames [rev], piMemorySize [mem], piMakerNames [maker], warranty ? "[Out of Warranty]" : "") ; + printf ("Raspberry Pi Details:\n") ; + printf (" Type: %s, Revision: %s, Memory: %dMB, Maker: %s %s\n", + piModelNames [model], piRevisionNames [rev], piMemorySize [mem], piMakerNames [maker], warranty ? "[Out of Warranty]" : "") ; // Check for device tree - if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... - printf (" Device tree is enabled.\n") ; + if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... + printf (" * Device tree is enabled.\n") ; - if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO - { - printf (" This Raspberry Pi supports user-level GPIO access.\n") ; - printf (" -> See the man-page for more details\n") ; - } - else - printf (" * Root or sudo required for GPIO access.\n") ; - + if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO + { + printf (" * This Raspberry Pi supports user-level GPIO access.\n") ; + printf (" -> See the man-page for more details\n") ; + printf (" -> ie. export WIRINGPI_GPIOMEM=1\n") ; } + else + printf (" * Root or sudo required for GPIO access.\n") ; } @@ -1285,11 +1277,24 @@ int main (int argc, char *argv []) if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; } if (strcasecmp (argv [1], "unload" ) == 0) { doUnLoad (argc, argv) ; return 0 ; } +// Check for usb power command + + if (strcasecmp (argv [1], "usbp" ) == 0) { doUsbP (argc, argv) ; return 0 ; } + // Gertboard commands if (strcasecmp (argv [1], "gbr" ) == 0) { doGbr (argc, argv) ; return 0 ; } if (strcasecmp (argv [1], "gbw" ) == 0) { doGbw (argc, argv) ; return 0 ; } +// Check for allreadall command, force Gpio mode + + if (strcasecmp (argv [1], "allreadall") == 0) + { + wiringPiSetupGpio () ; + doAllReadall () ; + return 0 ; + } + // Check for -g argument /**/ if (strcasecmp (argv [1], "-g") == 0) @@ -1379,7 +1384,6 @@ int main (int argc, char *argv []) else if (strcasecmp (argv [1], "pwmc" ) == 0) doPwmClock (argc, argv) ; else if (strcasecmp (argv [1], "pwmTone" ) == 0) doPwmTone (argc, argv) ; else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ; - else if (strcasecmp (argv [1], "usbp" ) == 0) doUsbP (argc, argv) ; else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ; else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ; else if (strcasecmp (argv [1], "pins" ) == 0) doPins () ; diff --git a/gpio/readall.c b/gpio/readall.c index 2d90cd1..cb7e18f 100644 --- a/gpio/readall.c +++ b/gpio/readall.c @@ -215,7 +215,14 @@ static void readallPhys (int physPin) } -void cmReadall (void) +/* + * allReadall: + * Read all the pins regardless of the model. Primarily of use for + * the compute module, but handy for other fiddling... + ********************************************************************************* + */ + +static void allReadall (void) { int pin ; @@ -223,19 +230,20 @@ void cmReadall (void) printf ("| Pin | Mode | Value | | Pin | Mode | Value |\n") ; printf ("+-----+------+-------+ +-----+------+-------+\n") ; - for (pin = 0 ; pin < 28 ; ++pin) + for (pin = 0 ; pin < 27 ; ++pin) { printf ("| %3d ", pin) ; printf ("| %-4s ", alts [getAlt (pin)]) ; printf ("| %s ", digitalRead (pin) == HIGH ? "High" : "Low ") ; printf ("| ") ; - printf ("| %3d ", pin + 28) ; - printf ("| %-4s ", alts [getAlt (pin + 28)]) ; - printf ("| %s ", digitalRead (pin + 28) == HIGH ? "High" : "Low ") ; + printf ("| %3d ", pin + 27) ; + printf ("| %-4s ", alts [getAlt (pin + 27)]) ; + printf ("| %s ", digitalRead (pin + 27) == HIGH ? "High" : "Low ") ; printf ("|\n") ; } printf ("+-----+------+-------+ +-----+------+-------+\n") ; + } @@ -291,12 +299,16 @@ static void plus2header (int model) printf (" +-----+-----+---------+------+---+--B Plus--+---+------+---------+-----+-----+\n") ; else if (model == PI_MODEL_ZERO) printf (" +-----+-----+---------+------+---+-Pi Zero--+---+------+---------+-----+-----+\n") ; - else + else if (model == PI_MODEL_2) printf (" +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+\n") ; + else if (model == PI_MODEL_3) + printf (" +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+\n") ; + else + printf (" +-----+-----+---------+------+---+---Pi ?---+---+------+---------+-----+-----+\n") ; } -void piPlusReadall (int model) +static void piPlusReadall (int model) { int pin ; @@ -313,6 +325,13 @@ void piPlusReadall (int model) } +/* + * doReadall: + * Generic read all pins called from main program. Works out the Pi type + * and calls the appropriate function. + ********************************************************************************* + */ + void doReadall (void) { int model, rev, mem, maker, overVolted ; @@ -327,10 +346,21 @@ void doReadall (void) /**/ if ((model == PI_MODEL_A) || (model == PI_MODEL_B)) abReadall (model, rev) ; - else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || (model == PI_MODEL_2) || (model == PI_MODEL_ZERO)) + else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || (model == PI_MODEL_2) || (model == PI_MODEL_3) || (model == PI_MODEL_ZERO)) piPlusReadall (model) ; else if (model == PI_MODEL_CM) - cmReadall () ; + allReadall () ; else printf ("Oops - unable to determine board type... model: %d\n", model) ; } + +/* + * doAllReadall: + * Force reading of all pins regardless of Pi model + ********************************************************************************* + */ + +void doAllReadall (void) +{ + allReadall () ; +} diff --git a/gpio/version.h b/gpio/version.h index 290ab36..5b92dc9 100644 --- a/gpio/version.h +++ b/gpio/version.h @@ -1 +1 @@ -#define VERSION "2.31" +#define VERSION "2.32" diff --git a/wiringPi/Makefile b/wiringPi/Makefile index 6bbcc5d..acb6e58 100644 --- a/wiringPi/Makefile +++ b/wiringPi/Makefile @@ -55,7 +55,7 @@ SRC = wiringPi.c \ sr595.c \ pcf8574.c pcf8591.c \ mcp3002.c mcp3004.c mcp4802.c mcp3422.c \ - max31855.c max5322.c \ + max31855.c max5322.c ads1115.c \ sn3218.c \ drcSerial.c \ wpiExtensions.c @@ -69,7 +69,7 @@ HEADERS = wiringPi.h \ sr595.h \ pcf8574.h pcf8591.h \ mcp3002.h mcp3004.h mcp4802.h mcp3422.h \ - max31855.h max5322.h \ + max31855.h max5322.h ads1115.h \ sn3218.h \ drcSerial.h \ wpiExtensions.h diff --git a/wiringPi/ads1115.c b/wiringPi/ads1115.c new file mode 100644 index 0000000..62b92f8 --- /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->data0 = dataRates [data] ; + } + +} + + +/* + * 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/drcSerial.c b/wiringPi/drcSerial.c index 6491a98..db7cc09 100644 --- a/wiringPi/drcSerial.c +++ b/wiringPi/drcSerial.c @@ -1,7 +1,7 @@ /* * drcSerial.c: * Extend wiringPi with the DRC Serial protocol (e.g. to Arduino) - * Copyright (c) 2013 Gordon Henderson + * Copyright (c) 2013-2016 Gordon Henderson *********************************************************************** * This file is part of wiringPi: * https://projects.drogon.net/raspberry-pi/wiringpi/ @@ -32,11 +32,6 @@ #include "drcSerial.h" -#ifndef TRUE -# define TRUE (1==1) -# define FALSE (1==2) -#endif - /* * myPinMode: @@ -156,7 +151,7 @@ int drcSetupSerial (const int pinBase, const int numPins, const char *device, co struct wiringPiNodeStruct *node ; if ((fd = serialOpen (device, baud)) < 0) - return wiringPiFailure (WPI_ALMOST, "Unable to open DRC device (%s): %s", device, strerror (errno)) ; + return FALSE ; delay (10) ; // May need longer if it's an Uno that reboots on the open... @@ -184,7 +179,7 @@ int drcSetupSerial (const int pinBase, const int numPins, const char *device, co if (!ok) { serialClose (fd) ; - return wiringPiFailure (WPI_FATAL, "Unable to communicate with DRC serial device") ; + return FALSE ; } node = wiringPiNewNode (pinBase, numPins) ; @@ -197,5 +192,5 @@ int drcSetupSerial (const int pinBase, const int numPins, const char *device, co node->digitalWrite = myDigitalWrite ; node->pwmWrite = myPwmWrite ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/max31855.c b/wiringPi/max31855.c index ea184d8..d86cabd 100644 --- a/wiringPi/max31855.c +++ b/wiringPi/max31855.c @@ -88,12 +88,12 @@ int max31855Setup (const int pinBase, int spiChannel) struct wiringPiNodeStruct *node ; if (wiringPiSPISetup (spiChannel, 5000000) < 0) // 5MHz - prob 4 on the Pi - return -1 ; + return FALSE ; node = wiringPiNewNode (pinBase, 4) ; node->fd = spiChannel ; node->analogRead = myAnalogRead ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/max5322.c b/wiringPi/max5322.c index b7cd6a9..e56b085 100644 --- a/wiringPi/max5322.c +++ b/wiringPi/max5322.c @@ -66,7 +66,7 @@ int max5322Setup (const int pinBase, int spiChannel) unsigned char spiData [2] ; if (wiringPiSPISetup (spiChannel, 8000000) < 0) // 10MHz Max - return -1 ; + return FALSE ; node = wiringPiNewNode (pinBase, 2) ; @@ -80,5 +80,5 @@ int max5322Setup (const int pinBase, int spiChannel) wiringPiSPIDataRW (node->fd, spiData, 2) ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/mcp23008.c b/wiringPi/mcp23008.c index d21d237..71757a8 100644 --- a/wiringPi/mcp23008.c +++ b/wiringPi/mcp23008.c @@ -132,7 +132,7 @@ int mcp23008Setup (const int pinBase, const int i2cAddress) struct wiringPiNodeStruct *node ; if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) - return fd ; + return FALSE ; wiringPiI2CWriteReg8 (fd, MCP23x08_IOCON, IOCON_INIT) ; @@ -145,5 +145,5 @@ int mcp23008Setup (const int pinBase, const int i2cAddress) node->digitalWrite = myDigitalWrite ; node->data2 = wiringPiI2CReadReg8 (fd, MCP23x08_OLAT) ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/mcp23016.c b/wiringPi/mcp23016.c index e5cc632..928d9e5 100644 --- a/wiringPi/mcp23016.c +++ b/wiringPi/mcp23016.c @@ -146,7 +146,7 @@ int mcp23016Setup (const int pinBase, const int i2cAddress) struct wiringPiNodeStruct *node ; if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) - return fd ; + return FALSE ; wiringPiI2CWriteReg8 (fd, MCP23016_IOCON0, IOCON_INIT) ; wiringPiI2CWriteReg8 (fd, MCP23016_IOCON1, IOCON_INIT) ; @@ -160,5 +160,5 @@ int mcp23016Setup (const int pinBase, const int i2cAddress) node->data2 = wiringPiI2CReadReg8 (fd, MCP23016_OLAT0) ; node->data3 = wiringPiI2CReadReg8 (fd, MCP23016_OLAT1) ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/mcp23017.c b/wiringPi/mcp23017.c index 5174195..4c3952d 100644 --- a/wiringPi/mcp23017.c +++ b/wiringPi/mcp23017.c @@ -177,7 +177,7 @@ int mcp23017Setup (const int pinBase, const int i2cAddress) struct wiringPiNodeStruct *node ; if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) - return fd ; + return FALSE ; wiringPiI2CWriteReg8 (fd, MCP23x17_IOCON, IOCON_INIT) ; @@ -191,5 +191,5 @@ int mcp23017Setup (const int pinBase, const int i2cAddress) node->data2 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATA) ; node->data3 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATB) ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/mcp23s08.c b/wiringPi/mcp23s08.c index d0acb5e..f293f3a 100644 --- a/wiringPi/mcp23s08.c +++ b/wiringPi/mcp23s08.c @@ -167,11 +167,10 @@ static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) int mcp23s08Setup (const int pinBase, const int spiPort, const int devId) { - int x ; struct wiringPiNodeStruct *node ; - if ((x = wiringPiSPISetup (spiPort, MCP_SPEED)) < 0) - return x ; + if (wiringPiSPISetup (spiPort, MCP_SPEED) < 0) + return FALSE ; writeByte (spiPort, devId, MCP23x08_IOCON, IOCON_INIT) ; @@ -185,5 +184,5 @@ int mcp23s08Setup (const int pinBase, const int spiPort, const int devId) node->digitalWrite = myDigitalWrite ; node->data2 = readByte (spiPort, devId, MCP23x08_OLAT) ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/mcp23s17.c b/wiringPi/mcp23s17.c index c2d1be3..42b0358 100644 --- a/wiringPi/mcp23s17.c +++ b/wiringPi/mcp23s17.c @@ -212,11 +212,10 @@ static int myDigitalRead (struct wiringPiNodeStruct *node, int pin) int mcp23s17Setup (const int pinBase, const int spiPort, const int devId) { - int x ; struct wiringPiNodeStruct *node ; - if ((x = wiringPiSPISetup (spiPort, MCP_SPEED)) < 0) - return x ; + 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) ; @@ -232,5 +231,5 @@ int mcp23s17Setup (const int pinBase, const int spiPort, const int devId) node->data2 = readByte (spiPort, devId, MCP23x17_OLATA) ; node->data3 = readByte (spiPort, devId, MCP23x17_OLATB) ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/mcp3002.c b/wiringPi/mcp3002.c index 5d44940..8e191b6 100644 --- a/wiringPi/mcp3002.c +++ b/wiringPi/mcp3002.c @@ -65,12 +65,12 @@ int mcp3002Setup (const int pinBase, int spiChannel) struct wiringPiNodeStruct *node ; if (wiringPiSPISetup (spiChannel, 1000000) < 0) - return -1 ; + return FALSE ; node = wiringPiNewNode (pinBase, 2) ; node->fd = spiChannel ; node->analogRead = myAnalogRead ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/mcp3004.c b/wiringPi/mcp3004.c index 82c73dd..be8383e 100644 --- a/wiringPi/mcp3004.c +++ b/wiringPi/mcp3004.c @@ -65,12 +65,12 @@ int mcp3004Setup (const int pinBase, int spiChannel) struct wiringPiNodeStruct *node ; if (wiringPiSPISetup (spiChannel, 1000000) < 0) - return -1 ; + return FALSE ; node = wiringPiNewNode (pinBase, 8) ; node->fd = spiChannel ; node->analogRead = myAnalogRead ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/mcp3422.c b/wiringPi/mcp3422.c index 831aece..be14db6 100644 --- a/wiringPi/mcp3422.c +++ b/wiringPi/mcp3422.c @@ -1,8 +1,9 @@ /* * mcp3422.c: - * Extend wiringPi with the MCP3422 I2C ADC chip - * Also works for the MCP3423 and MCP3224 (4 channel) chips - * Copyright (c) 2013 Gordon Henderson + * 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/ @@ -29,7 +30,6 @@ #include #include #include -#include #include #include @@ -37,6 +37,23 @@ #include "mcp3422.h" +/* + * waitForConversion: + * Common code to wait for the ADC to finish conversion + ********************************************************************************* + */ + +void waitForConversion (int fd, unsigned char *buffer, int n) +{ + for (;;) + { + read (fd, buffer, n) ; + if ((buffer [n-1] & 0x80) == 0) + break ; + delay (1) ; + } +} + /* * myAnalogRead: * Read a channel from the device @@ -48,37 +65,34 @@ 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 | ((chan - node->pinBase) << 5) | (node->data0 << 2) | (node->data1) ; + 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 - delay (270) ; - read (node->fd, buffer, 4) ; - value = ((buffer [0] & 3) << 16) | (buffer [1] << 8) | buffer [0] ; + waitForConversion (node->fd, &buffer [0], 4) ; + value = ((buffer [0] & 3) << 16) | (buffer [1] << 8) | buffer [2] ; break ; case MCP3422_SR_15: // 16 bits - delay ( 70) ; - read (node->fd, buffer, 3) ; + waitForConversion (node->fd, buffer, 3) ; value = (buffer [0] << 8) | buffer [1] ; break ; case MCP3422_SR_60: // 14 bits - delay ( 17) ; - read (node->fd, buffer, 3) ; + waitForConversion (node->fd, buffer, 3) ; value = ((buffer [0] & 0x3F) << 8) | buffer [1] ; break ; - case MCP3422_SR_240: // 12 bits - delay ( 5) ; - read (node->fd, buffer, 3) ; - value = ((buffer [0] & 0x0F) << 8) | buffer [0] ; + case MCP3422_SR_240: // 12 bits - default + waitForConversion (node->fd, buffer, 3) ; + value = ((buffer [0] & 0x0F) << 8) | buffer [1] ; break ; } @@ -98,13 +112,14 @@ int mcp3422Setup (int pinBase, int i2cAddress, int sampleRate, int gain) struct wiringPiNodeStruct *node ; if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) - return fd ; + return FALSE ; node = wiringPiNewNode (pinBase, 4) ; + node->fd = fd ; node->data0 = sampleRate ; node->data1 = gain ; node->analogRead = myAnalogRead ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/mcp3422.h b/wiringPi/mcp3422.h index bb4692d..72647d4 100644 --- a/wiringPi/mcp3422.h +++ b/wiringPi/mcp3422.h @@ -1,6 +1,6 @@ /* - * mcp3422.c: - * Extend wiringPi with the MCP3422 I2C ADC chip + * 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/ @@ -21,10 +21,10 @@ *********************************************************************** */ -#define MCP3422_SR_3_75 0 -#define MCP3422_SR_15 1 -#define MCP3422_SR_60 2 -#define MCP3422_SR_240 3 +#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 diff --git a/wiringPi/mcp4802.c b/wiringPi/mcp4802.c index 5c5c17a..ef104ed 100644 --- a/wiringPi/mcp4802.c +++ b/wiringPi/mcp4802.c @@ -65,12 +65,12 @@ int mcp4802Setup (const int pinBase, int spiChannel) struct wiringPiNodeStruct *node ; if (wiringPiSPISetup (spiChannel, 1000000) < 0) - return -1 ; + return FALSE ; node = wiringPiNewNode (pinBase, 2) ; node->fd = spiChannel ; node->analogWrite = myAnalogWrite ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/pcf8574.c b/wiringPi/pcf8574.c index c172d1c..e0b686a 100644 --- a/wiringPi/pcf8574.c +++ b/wiringPi/pcf8574.c @@ -112,7 +112,7 @@ int pcf8574Setup (const int pinBase, const int i2cAddress) struct wiringPiNodeStruct *node ; if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) - return fd ; + return FALSE ; node = wiringPiNewNode (pinBase, 8) ; @@ -122,5 +122,5 @@ int pcf8574Setup (const int pinBase, const int i2cAddress) node->digitalWrite = myDigitalWrite ; node->data2 = wiringPiI2CRead (fd) ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/pcf8591.c b/wiringPi/pcf8591.c index 0c86056..0c43d26 100644 --- a/wiringPi/pcf8591.c +++ b/wiringPi/pcf8591.c @@ -78,7 +78,7 @@ int pcf8591Setup (const int pinBase, const int i2cAddress) struct wiringPiNodeStruct *node ; if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) - return fd ; + return FALSE ; node = wiringPiNewNode (pinBase, 4) ; @@ -86,5 +86,5 @@ int pcf8591Setup (const int pinBase, const int i2cAddress) node->analogRead = myAnalogRead ; node->analogWrite = myAnalogWrite ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/sn3218.c b/wiringPi/sn3218.c index 7ceb156..d9b9113 100644 --- a/wiringPi/sn3218.c +++ b/wiringPi/sn3218.c @@ -55,7 +55,7 @@ int sn3218Setup (const int pinBase) struct wiringPiNodeStruct *node ; if ((fd = wiringPiI2CSetup (0x54)) < 0) - return fd ; + return FALSE ; // Setup the chip - initialise all 18 LEDs to off @@ -71,5 +71,5 @@ int sn3218Setup (const int pinBase) node->fd = fd ; node->analogWrite = myAnalogWrite ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/softPwm.c b/wiringPi/softPwm.c index 391f0f1..98b408f 100644 --- a/wiringPi/softPwm.c +++ b/wiringPi/softPwm.c @@ -83,11 +83,11 @@ static PI_THREAD (softPwmThread) if (mark != 0) digitalWrite (pin, HIGH) ; - delayMicroseconds (mark * PULSE_TIME) ; + delayMicroseconds (mark * 100) ; if (space != 0) digitalWrite (pin, LOW) ; - delayMicroseconds (space * PULSE_TIME) ; + delayMicroseconds (space * 100) ; } return NULL ; diff --git a/wiringPi/sr595.c b/wiringPi/sr595.c index 87210c2..8280618 100644 --- a/wiringPi/sr595.c +++ b/wiringPi/sr595.c @@ -105,5 +105,5 @@ int sr595Setup (const int pinBase, const int numPins, pinMode (clockPin, OUTPUT) ; pinMode (latchPin, OUTPUT) ; - return 0 ; + return TRUE ; } diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 503151f..dfd5de4 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -69,17 +69,13 @@ #include #include #include +#include #include "softPwm.h" #include "softTone.h" #include "wiringPi.h" -#ifndef TRUE -#define TRUE (1==1) -#define FALSE (1==2) -#endif - // Environment Variables #define ENV_DEBUG "WIRINGPI_DEBUG" @@ -219,7 +215,7 @@ const char *piModelNames [16] = "Alpha", // 5 "CM", // 6 "Unknown07", // 07 - "Unknown08", // 08 + "Pi 3", // 08 "Pi Zero", // 09 "Unknown10", // 10 "Unknown11", // 11 @@ -461,6 +457,7 @@ static uint8_t gpioToShift [] = 0,3,6,9,12,15,18,21,24,27, 0,3,6,9,12,15,18,21,24,27, 0,3,6,9,12,15,18,21,24,27, + 0,3,6,9,12,15,18,21,24,27, } ; @@ -893,7 +890,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) *c = 0 ; if (wiringPiDebug) - printf ("piboardId: Revision string: %s\n", line) ; + printf ("piBoardId: Revision string: %s\n", line) ; // Need to work out if it's using the new or old encoding scheme: @@ -1623,16 +1620,21 @@ void pwmToneWrite (int pin, int freq) /* * digitalWriteByte: + * digitalReadByte: * Pi Specific * Write an 8-bit byte to the first 8 GPIO pins - try to do it as * fast as possible. * However it still needs 2 operations to set the bits, so any external * hardware must not rely on seeing a change as there will be a change * to set the outputs bits to zero, then another change to set the 1's + * Reading is just bit fiddling. + * These are wiringPi pin numbers 0..7, or BCM_GPIO pin numbers + * 17, 18, 22, 23, 24, 24, 4 on a Pi v1 rev 0-3 + * 17, 18, 27, 23, 24, 24, 4 on a Pi v1 rev 3 onwards or B+, 2, zero ********************************************************************************* */ -void digitalWriteByte (int value) +void digitalWriteByte (const int value) { uint32_t pinSet = 0 ; uint32_t pinClr = 0 ; @@ -1643,7 +1645,7 @@ void digitalWriteByte (int value) { for (pin = 0 ; pin < 8 ; ++pin) { - digitalWrite (pin, value & mask) ; + digitalWrite (pinToGpio [pin], value & mask) ; mask <<= 1 ; } return ; @@ -1665,6 +1667,83 @@ void digitalWriteByte (int value) } } +unsigned int digitalReadByte (void) +{ + int pin, x ; + uint32_t raw ; + uint32_t data = 0 ; + + /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + { + for (pin = 0 ; pin < 8 ; ++pin) + { + x = digitalRead (pinToGpio [pin]) ; + data = (data << 1) | x ; + } + } + else + { + raw = *(gpio + gpioToGPLEV [0]) ; // First bank for these pins + for (pin = 0 ; pin < 8 ; ++pin) + { + x = pinToGpio [pin] ; + data = (data << 1) | (((raw & (1 << x)) == 0) ? 0 : 1) ; + } + } + return data ; +} + + +/* + * digitalWriteByte2: + * digitalReadByte2: + * Pi Specific + * Write an 8-bit byte to the second set of 8 GPIO pins. This is marginally + * faster than the first lot as these are consecutive BCM_GPIO pin numbers. + * However they overlap with the original read/write bytes. + ********************************************************************************* + */ + +void digitalWriteByte2 (const int value) +{ + register int mask = 1 ; + register int pin ; + + /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + { + for (pin = 20 ; pin < 28 ; ++pin) + { + digitalWrite (pin, value & mask) ; + mask <<= 1 ; + } + return ; + } + else + { + *(gpio + gpioToGPCLR [0]) = 0x0FF00000 ; + *(gpio + gpioToGPSET [0]) = (value & 0xFF) << 20 ; + } +} + +unsigned int digitalReadByte2 (void) +{ + int pin, x ; + uint32_t data = 0 ; + + /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) + { + for (pin = 20 ; pin < 28 ; ++pin) + { + x = digitalRead (pin) ; + data = (data << 1) | x ; + } + } + else + data = ((*(gpio + gpioToGPLEV [0])) >> 20) & 0xFF ; // First bank for these pins + + return data ; +} + /* * waitForInterrupt: @@ -1970,6 +2049,16 @@ int wiringPiSetup (void) int fd ; int boardRev ; int model, rev, mem, maker, overVolted ; + static int alreadyCalled = FALSE ; + +// This is here to trap the unwary - those who's program appears to work then fails some +// time later with a weird error message because you run out of file-handles. + + if (alreadyCalled) + (void)wiringPiFailure (WPI_FATAL, "wiringPiSetup*: You must only call this once per program run. This is a fatal error. Please fix your code.\n") ; + + alreadyCalled = TRUE ; + if (getenv (ENV_DEBUG) != NULL) wiringPiDebug = TRUE ; @@ -1994,12 +2083,14 @@ int wiringPiSetup (void) pinToGpio = pinToGpioR1 ; physToGpio = physToGpioR1 ; } - else // A, B, Rev 2, B+, CM, Pi2 + else // A, B, Rev 2, B+, CM, Pi2, Zero { pinToGpio = pinToGpioR2 ; physToGpio = physToGpioR2 ; } +// Note that a Zero is a model 1 + if (piModel2) RASPBERRY_PI_PERI_BASE = 0x3F000000 ; else @@ -2153,6 +2244,15 @@ int wiringPiSetupSys (void) int boardRev ; int pin ; char fName [128] ; + static int alreadyCalled = FALSE ; + +// This is here to trap the unwary - those who's program appears to work then fails some +// time later with a weird error message because you run out of file-handles. + + if (alreadyCalled) + (void)wiringPiFailure (WPI_FATAL, "wiringPiSetupSys: You must only call this once per program run. This is a fatal error. Please fix your code.\n") ; + + alreadyCalled = TRUE ; if (getenv (ENV_DEBUG) != NULL) wiringPiDebug = TRUE ; diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 7b9605f..e11a0be 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -1,7 +1,7 @@ /* - * wiringPi: - * Arduino compatable (ish) Wiring library for the Raspberry Pi - * Copyright (c) 2012 Gordon Henderson + * wiringPi.h: + * Arduino like Wiring library for the Raspberry Pi. + * Copyright (c) 2012-2016 Gordon Henderson *********************************************************************** * This file is part of wiringPi: * https://projects.drogon.net/raspberry-pi/wiringpi/ @@ -24,6 +24,14 @@ #ifndef __WIRING_PI_H__ #define __WIRING_PI_H__ +// C doesn't have true/false by default and I can never remember which +// way round they are, so ... + +#ifndef TRUE +# define TRUE (1==1) +# define FALSE (!TRUE) +#endif + // Handy defines // wiringPi modes @@ -77,7 +85,7 @@ #define PI_ALPHA 5 #define PI_MODEL_CM 6 #define PI_MODEL_07 7 -#define PI_MODEL_08 8 +#define PI_MODEL_3 8 #define PI_MODEL_ZERO 9 #define PI_VERSION_1 0 @@ -182,18 +190,19 @@ extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio // On-Board Raspberry Pi hardware specific stuff -extern int piBoardRev (void) ; -extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; -extern int wpiPinToGpio (int wpiPin) ; -extern int physPinToGpio (int physPin) ; -extern void setPadDrive (int group, int value) ; -extern int getAlt (int pin) ; -extern void pwmToneWrite (int pin, int freq) ; -extern void digitalWriteByte (int value) ; -extern void pwmSetMode (int mode) ; -extern void pwmSetRange (unsigned int range) ; -extern void pwmSetClock (int divisor) ; -extern void gpioClockSet (int pin, int freq) ; +extern int piBoardRev (void) ; +extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; +extern int wpiPinToGpio (int wpiPin) ; +extern int physPinToGpio (int physPin) ; +extern void setPadDrive (int group, int value) ; +extern int getAlt (int pin) ; +extern void pwmToneWrite (int pin, int freq) ; +extern void digitalWriteByte (int value) ; +extern unsigned int digitalReadByte (void) ; +extern void pwmSetMode (int mode) ; +extern void pwmSetRange (unsigned int range) ; +extern void pwmSetClock (int divisor) ; +extern void gpioClockSet (int pin, int freq) ; // Interrupts // (Also Pi hardware specific) diff --git a/wiringPi/wpiExtensions.c b/wiringPi/wpiExtensions.c index 4cae9c4..62a92d7 100644 --- a/wiringPi/wpiExtensions.c +++ b/wiringPi/wpiExtensions.c @@ -52,6 +52,7 @@ #include "mcp3422.h" #include "max31855.h" #include "max5322.h" +#include "ads1115.h" #include "sn3218.h" #include "drcSerial.h" @@ -63,11 +64,6 @@ static int verbose ; static char errorMessage [1024] ; -#ifndef TRUE -# define TRUE (1==1) -# define FALSE (1==2) -#endif - // Local structure to hold details struct extensionFunctionStruct @@ -118,7 +114,13 @@ static char *extractInt (char *progName, char *p, int *num) } *num = strtol (p, NULL, 0) ; - while (isdigit (*p)) + +// Increment p, but we need to check for hex 0x + + if ((*p == '0') && (*(p + 1) == 'x')) + p +=2 ; + + while (isxdigit (*p)) ++p ; return p ; @@ -374,6 +376,32 @@ static int doExtensionPcf8574 (char *progName, int pinBase, char *params) } +/* + * 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 @@ -654,6 +682,7 @@ static struct extensionFunctionStruct extensionFunctions [] = { "mcp4802", &doExtensionMcp4802 }, { "mcp3422", &doExtensionMcp3422 }, { "max31855", &doExtensionMax31855 }, + { "ads1115", &doExtensionAds1115 }, { "max5322", &doExtensionMax5322 }, { "sn3218", &doExtensionSn3218 }, { "drcs", &doExtensionDrcS }, @@ -674,7 +703,7 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors) char *p ; char *extension = extensionData ; struct extensionFunctionStruct *extensionFn ; - int pinBase = 0 ; + unsigned pinBase = 0 ; verbose = printErrors ; @@ -696,13 +725,13 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors) if (!isdigit (*p)) { - verbError ("%s: pinBase number expected after extension name", progName) ; + verbError ("%s: decimal pinBase number expected after extension name", progName) ; return FALSE ; } while (isdigit (*p)) { - if (pinBase > 1000000000) // Lets be realistic here... + if (pinBase > 2147483647) // 2^31-1 ... Lets be realistic here... { verbError ("%s: pinBase too large", progName) ; return FALSE ;