mirror of
https://github.com/clockworkpi/WiringPi.git
synced 2026-03-20 19:02:54 +01:00
Bumped the version to 2.40 - correctly this time, I hope.
Added fixed for a few minor things. pin driver for rht03/dht type sensors. Network stuff is experimental - for now.
This commit is contained in:
@@ -57,8 +57,8 @@ SRC = wiringPi.c \
|
||||
mcp3002.c mcp3004.c mcp4802.c mcp3422.c \
|
||||
max31855.c max5322.c ads1115.c \
|
||||
sn3218.c \
|
||||
bmp180.c htu21d.c ds18b20.c \
|
||||
drcSerial.c \
|
||||
bmp180.c htu21d.c ds18b20.c rht03.c \
|
||||
drcSerial.c drcNet.c \
|
||||
pseudoPins.c \
|
||||
wpiExtensions.c
|
||||
|
||||
|
||||
405
wiringPi/drcNet.c
Normal file
405
wiringPi/drcNet.c
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <crypt.h>
|
||||
|
||||
|
||||
#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 ;
|
||||
|
||||
sprintf (salted, "$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 ;
|
||||
}
|
||||
42
wiringPi/drcNet.h
Normal file
42
wiringPi/drcNet.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
/*********
|
||||
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
|
||||
126
wiringPi/rht03.c
Normal file
126
wiringPi/rht03.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
//#include <sys/types.h>
|
||||
//#include <sys/stat.h>
|
||||
//#include <fcntl.h>
|
||||
|
||||
//#include <unistd.h>
|
||||
//#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
//#include <string.h>
|
||||
#include <time.h>
|
||||
//#include <ctype.h>
|
||||
|
||||
#include "wiringPi.h"
|
||||
#include "../devLib/maxdetect.h"
|
||||
|
||||
#include "rht03.h"
|
||||
|
||||
|
||||
/*
|
||||
* 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 ;
|
||||
}
|
||||
25
wiringPi/rht03.h
Normal file
25
wiringPi/rht03.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
extern int rht03Setup (const int pinBase, const int devicePin) ;
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* softPwm.c:
|
||||
* Provide 2 channels of software driven PWM.
|
||||
* Copyright (c) 2012-2014 Gordon Henderson
|
||||
* Provide many channels of software driven PWM.
|
||||
* Copyright (c) 2012-2017 Gordon Henderson
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
||||
@@ -30,11 +30,11 @@
|
||||
#include "softPwm.h"
|
||||
|
||||
// MAX_PINS:
|
||||
// This is more than the number of Pi pins because we can actually softPwm
|
||||
// pins that are on GPIO expanders. It's not that efficient and more than 1 or
|
||||
// 2 pins on e.g. (SPI) mcp23s17 won't really be that effective, however...
|
||||
// This is more than the number of Pi pins because we can actually softPwm.
|
||||
// Once upon a time I let pins on gpio expanders be softPwm'd, but it's really
|
||||
// really not a good thing.
|
||||
|
||||
#define MAX_PINS 1024
|
||||
#define MAX_PINS 64
|
||||
|
||||
// The PWM Frequency is derived from the "pulse time" below. Essentially,
|
||||
// the frequency is a function of the range and this pulse time.
|
||||
@@ -45,7 +45,7 @@
|
||||
// It's possible to get a higher frequency by lowering the pulse time,
|
||||
// however CPU uage will skyrocket as wiringPi uses a hard-loop to time
|
||||
// periods under 100µS - this is because the Linux timer calls are just
|
||||
// accurate at all, and have an overhead.
|
||||
// not accurate at all, and have an overhead.
|
||||
//
|
||||
// Another way to increase the frequency is to reduce the range - however
|
||||
// that reduces the overall output accuracy...
|
||||
@@ -106,14 +106,15 @@ static void *softPwmThread (void *arg)
|
||||
|
||||
void softPwmWrite (int pin, int value)
|
||||
{
|
||||
pin &= (MAX_PINS - 1) ;
|
||||
if (pin < MAX_PINS)
|
||||
{
|
||||
/**/ if (value < 0)
|
||||
value = 0 ;
|
||||
else if (value > range [pin])
|
||||
value = range [pin] ;
|
||||
|
||||
/**/ if (value < 0)
|
||||
value = 0 ;
|
||||
else if (value > range [pin])
|
||||
value = range [pin] ;
|
||||
|
||||
marks [pin] = value ;
|
||||
marks [pin] = value ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +130,9 @@ int softPwmCreate (int pin, int initialValue, int pwmRange)
|
||||
pthread_t myThread ;
|
||||
int *passPin ;
|
||||
|
||||
if (pin >= MAX_PINS)
|
||||
return -1 ;
|
||||
|
||||
if (range [pin] != 0) // Already running on this pin
|
||||
return -1 ;
|
||||
|
||||
@@ -139,15 +143,15 @@ int softPwmCreate (int pin, int initialValue, int pwmRange)
|
||||
if (passPin == NULL)
|
||||
return -1 ;
|
||||
|
||||
pinMode (pin, OUTPUT) ;
|
||||
digitalWrite (pin, LOW) ;
|
||||
pinMode (pin, OUTPUT) ;
|
||||
|
||||
marks [pin] = initialValue ;
|
||||
range [pin] = pwmRange ;
|
||||
|
||||
*passPin = pin ;
|
||||
newPin = pin ;
|
||||
res = pthread_create (&myThread, NULL, softPwmThread, (void *)passPin) ;
|
||||
newPin = pin ;
|
||||
res = pthread_create (&myThread, NULL, softPwmThread, (void *)passPin) ;
|
||||
|
||||
while (newPin != -1)
|
||||
delay (1) ;
|
||||
@@ -166,11 +170,14 @@ int softPwmCreate (int pin, int initialValue, int pwmRange)
|
||||
|
||||
void softPwmStop (int pin)
|
||||
{
|
||||
if (range [pin] != 0)
|
||||
if (pin < MAX_PINS)
|
||||
{
|
||||
pthread_cancel (threads [pin]) ;
|
||||
pthread_join (threads [pin], NULL) ;
|
||||
range [pin] = 0 ;
|
||||
digitalWrite (pin, LOW) ;
|
||||
if (range [pin] != 0)
|
||||
{
|
||||
pthread_cancel (threads [pin]) ;
|
||||
pthread_join (threads [pin], NULL) ;
|
||||
range [pin] = 0 ;
|
||||
digitalWrite (pin, LOW) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,10 +84,8 @@
|
||||
#define ENV_GPIOMEM "WIRINGPI_GPIOMEM"
|
||||
|
||||
|
||||
// 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)
|
||||
// Extend wiringPi with other pin-based devices and keep track of
|
||||
// them in this structure
|
||||
|
||||
struct wiringPiNodeStruct *wiringPiNodes = NULL ;
|
||||
|
||||
@@ -1244,13 +1242,15 @@ struct wiringPiNodeStruct *wiringPiFindNode (int pin)
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
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 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 ; }
|
||||
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 digitalRead8Dummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return 0 ; }
|
||||
static void 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)
|
||||
{
|
||||
@@ -1272,17 +1272,19 @@ struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins)
|
||||
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->digitalWrite = digitalWriteDummy ;
|
||||
node->pwmWrite = pwmWriteDummy ;
|
||||
node->analogRead = analogReadDummy ;
|
||||
node->analogWrite = analogWriteDummy ;
|
||||
node->next = wiringPiNodes ;
|
||||
wiringPiNodes = node ;
|
||||
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 ;
|
||||
}
|
||||
@@ -1492,6 +1494,27 @@ int digitalRead (int pin)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* digitalRead8:
|
||||
* Read 8-bits (a byte) from given start pin.
|
||||
*********************************************************************************
|
||||
|
||||
unsigned int digitalRead8 (int pin)
|
||||
{
|
||||
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
||||
|
||||
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
|
||||
return 0 ;
|
||||
else
|
||||
{
|
||||
if ((node = wiringPiFindNode (pin)) == NULL)
|
||||
return LOW ;
|
||||
return node->digitalRead8 (node, pin) ;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* digitalWrite:
|
||||
* Set an output bit
|
||||
@@ -1535,6 +1558,26 @@ void digitalWrite (int pin, int value)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* digitalWrite8:
|
||||
* Set an output 8-bit byte on the device from the given pin number
|
||||
*********************************************************************************
|
||||
|
||||
void digitalWrite8 (int pin, int value)
|
||||
{
|
||||
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
||||
|
||||
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
|
||||
return ;
|
||||
else
|
||||
{
|
||||
if ((node = wiringPiFindNode (pin)) != NULL)
|
||||
node->digitalWrite8 (node, pin, value) ;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* pwmWrite:
|
||||
* Set an output PWM value
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
// C doesn't have true/false by default and I can never remember which
|
||||
// way round they are, so ...
|
||||
// (and yes, I know about stdbool.h but I like capitals for these and I'm old)
|
||||
|
||||
#ifndef TRUE
|
||||
# define TRUE (1==1)
|
||||
@@ -36,6 +37,11 @@
|
||||
|
||||
#define UNU __attribute__((unused))
|
||||
|
||||
// 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)
|
||||
|
||||
// Handy defines
|
||||
|
||||
// wiringPi modes
|
||||
@@ -140,13 +146,15 @@ struct wiringPiNodeStruct
|
||||
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) ;
|
||||
void (*digitalWrite) (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) ;
|
||||
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 ;
|
||||
} ;
|
||||
@@ -179,14 +187,16 @@ extern int wiringPiSetupSys (void) ;
|
||||
extern int wiringPiSetupGpio (void) ;
|
||||
extern int wiringPiSetupPhys (void) ;
|
||||
|
||||
extern void pinModeAlt (int pin, int mode) ;
|
||||
extern void pinMode (int pin, int mode) ;
|
||||
extern void pullUpDnControl (int pin, int pud) ;
|
||||
extern int digitalRead (int pin) ;
|
||||
extern void digitalWrite (int pin, int value) ;
|
||||
extern void pwmWrite (int pin, int value) ;
|
||||
extern int analogRead (int pin) ;
|
||||
extern void analogWrite (int pin, int value) ;
|
||||
extern void pinModeAlt (int pin, int mode) ;
|
||||
extern void pinMode (int pin, int mode) ;
|
||||
extern void pullUpDnControl (int pin, int pud) ;
|
||||
extern int digitalRead (int pin) ;
|
||||
extern void digitalWrite (int pin, int value) ;
|
||||
extern unsigned int digitalRead8 (int pin) ;
|
||||
extern void digitalWrite8 (int pin, int value) ;
|
||||
extern void pwmWrite (int pin, int value) ;
|
||||
extern int analogRead (int pin) ;
|
||||
extern void analogWrite (int pin, int value) ;
|
||||
|
||||
// PiFace specifics
|
||||
// (Deprecated)
|
||||
@@ -204,12 +214,14 @@ 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) ;
|
||||
extern unsigned int digitalReadByte (void) ;
|
||||
extern unsigned int digitalReadByte2 (void) ;
|
||||
extern void digitalWriteByte (int value) ;
|
||||
extern void digitalWriteByte2 (int value) ;
|
||||
|
||||
// Interrupts
|
||||
// (Also Pi hardware specific)
|
||||
|
||||
@@ -55,10 +55,13 @@
|
||||
#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"
|
||||
|
||||
@@ -134,12 +137,16 @@ static char *extractInt (char *progName, char *p, int *num)
|
||||
/*
|
||||
* 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 != ':')
|
||||
{
|
||||
@@ -149,21 +156,38 @@ static char *extractStr (char *progName, char *p, char **str)
|
||||
|
||||
++p ;
|
||||
|
||||
if (!isprint (*p))
|
||||
if (*p == '[')
|
||||
{
|
||||
quoted = TRUE ;
|
||||
++p ;
|
||||
}
|
||||
|
||||
if (!isprint (*p)) // Is this needed?
|
||||
{
|
||||
verbError ("%s: character expected", progName) ;
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
q = p ;
|
||||
while ((*q != 0) && (*q != ':'))
|
||||
++q ;
|
||||
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 ;
|
||||
}
|
||||
|
||||
@@ -495,6 +519,24 @@ static int doExtensionDs18b20 (char *progName, int pinBase, char *params)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -698,9 +740,9 @@ static int doExtensionDrcS (char *progName, int pinBase, char *params)
|
||||
if ((params = extractInt (progName, params, &pins)) == NULL)
|
||||
return FALSE ;
|
||||
|
||||
if ((pins < 1) || (pins > 100))
|
||||
if ((pins < 1) || (pins > 1000))
|
||||
{
|
||||
verbError ("%s: pins (%d) out of range (2-100)", progName, pins) ;
|
||||
verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ;
|
||||
return FALSE ;
|
||||
}
|
||||
|
||||
@@ -728,6 +770,59 @@ static int doExtensionDrcS (char *progName, int pinBase, char *params)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -748,6 +843,7 @@ static struct extensionFunctionStruct extensionFunctions [] =
|
||||
{ "pseudoPins", &doExtensionPseudoPins },
|
||||
{ "htu21d", &doExtensionHtu21d },
|
||||
{ "ds18b20", &doExtensionDs18b20 },
|
||||
{ "rht03", &doExtensionRht03 },
|
||||
{ "mcp3002", &doExtensionMcp3002 },
|
||||
{ "mcp3004", &doExtensionMcp3004 },
|
||||
{ "mcp4802", &doExtensionMcp4802 },
|
||||
@@ -757,6 +853,7 @@ static struct extensionFunctionStruct extensionFunctions [] =
|
||||
{ "max5322", &doExtensionMax5322 },
|
||||
{ "sn3218", &doExtensionSn3218 },
|
||||
{ "drcs", &doExtensionDrcS },
|
||||
{ "drcn", &doExtensionDrcNet },
|
||||
{ NULL, NULL },
|
||||
} ;
|
||||
|
||||
@@ -826,6 +923,6 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors)
|
||||
return extensionFn->function (progName, pinBase, p) ;
|
||||
}
|
||||
|
||||
verbError ("%s: extension %s not found", progName, extension) ;
|
||||
fprintf (stderr, "%s: extension %s not found", progName, extension) ;
|
||||
return FALSE ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user