197 lines
5.0 KiB
C
197 lines
5.0 KiB
C
|
/*
|
||
|
* drcSerial.c:
|
||
|
* Extend wiringPi with the DRC Serial protocol (e.g. to Arduino)
|
||
|
* Copyright (c) 2013-2016 Gordon Henderson
|
||
|
***********************************************************************
|
||
|
* This file is part of wiringPi:
|
||
|
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
||
|
*
|
||
|
* wiringPi is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU Lesser General Public License as
|
||
|
* published by the Free Software Foundation, either version 3 of the
|
||
|
* License, or (at your option) any later version.
|
||
|
*
|
||
|
* wiringPi is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public
|
||
|
* License along with wiringPi.
|
||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <time.h>
|
||
|
#include <string.h>
|
||
|
#include <errno.h>
|
||
|
|
||
|
#include "wiringPi.h"
|
||
|
#include "wiringSerial.h"
|
||
|
|
||
|
#include "drcSerial.h"
|
||
|
|
||
|
|
||
|
/*
|
||
|
* myPinMode:
|
||
|
* Change the pin mode on the remote DRC device
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode)
|
||
|
{
|
||
|
/**/ if (mode == OUTPUT)
|
||
|
serialPutchar (node->fd, 'o') ; // Input
|
||
|
else if (mode == PWM_OUTPUT)
|
||
|
serialPutchar (node->fd, 'p') ; // PWM
|
||
|
else
|
||
|
serialPutchar (node->fd, 'i') ; // Default to input
|
||
|
|
||
|
serialPutchar (node->fd, pin - node->pinBase) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* myPullUpDnControl:
|
||
|
* ATmegas only have pull-up's on of off. No pull-downs.
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode)
|
||
|
{
|
||
|
|
||
|
// Force pin into input mode
|
||
|
|
||
|
serialPutchar (node->fd, 'i' ) ;
|
||
|
serialPutchar (node->fd, pin - node->pinBase) ;
|
||
|
|
||
|
/**/ if (mode == PUD_UP)
|
||
|
{
|
||
|
serialPutchar (node->fd, '1') ;
|
||
|
serialPutchar (node->fd, pin - node->pinBase) ;
|
||
|
}
|
||
|
else if (mode == PUD_OFF)
|
||
|
{
|
||
|
serialPutchar (node->fd, '0') ;
|
||
|
serialPutchar (node->fd, pin - node->pinBase) ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* myDigitalWrite:
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value)
|
||
|
{
|
||
|
serialPutchar (node->fd, value == 0 ? '0' : '1') ;
|
||
|
serialPutchar (node->fd, pin - node->pinBase) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* myPwmWrite:
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
static void myPwmWrite (struct wiringPiNodeStruct *node, int pin, int value)
|
||
|
{
|
||
|
serialPutchar (node->fd, 'v') ;
|
||
|
serialPutchar (node->fd, pin - node->pinBase) ;
|
||
|
serialPutchar (node->fd, value & 0xFF) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* myAnalogRead:
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
|
||
|
{
|
||
|
int vHi, vLo ;
|
||
|
|
||
|
serialPutchar (node->fd, 'a') ;
|
||
|
serialPutchar (node->fd, pin - node->pinBase) ;
|
||
|
vHi = serialGetchar (node->fd) ;
|
||
|
vLo = serialGetchar (node->fd) ;
|
||
|
|
||
|
return (vHi << 8) | vLo ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* myDigitalRead:
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
static int myDigitalRead (struct wiringPiNodeStruct *node, int pin)
|
||
|
{
|
||
|
serialPutchar (node->fd, 'r') ; // Send read command
|
||
|
serialPutchar (node->fd, pin - node->pinBase) ;
|
||
|
return (serialGetchar (node->fd) == '0') ? 0 : 1 ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* drcSetup:
|
||
|
* Create a new instance of an DRC GPIO interface.
|
||
|
* Could be a variable nunber of pins here - we might not know in advance
|
||
|
* if it's an ATmega with 14 pins, or something with less or more!
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
int drcSetupSerial (const int pinBase, const int numPins, const char *device, const int baud)
|
||
|
{
|
||
|
int fd ;
|
||
|
int ok, tries ;
|
||
|
time_t then ;
|
||
|
struct wiringPiNodeStruct *node ;
|
||
|
|
||
|
if ((fd = serialOpen (device, baud)) < 0)
|
||
|
return FALSE ;
|
||
|
|
||
|
delay (10) ; // May need longer if it's an Uno that reboots on the open...
|
||
|
|
||
|
// Flush any pending input
|
||
|
|
||
|
while (serialDataAvail (fd))
|
||
|
(void)serialGetchar (fd) ;
|
||
|
|
||
|
ok = FALSE ;
|
||
|
for (tries = 1 ; (tries < 5) && (!ok) ; ++tries)
|
||
|
{
|
||
|
serialPutchar (fd, '@') ; // Ping
|
||
|
then = time (NULL) + 2 ;
|
||
|
while (time (NULL) < then)
|
||
|
if (serialDataAvail (fd))
|
||
|
{
|
||
|
if (serialGetchar (fd) == '@')
|
||
|
{
|
||
|
ok = TRUE ;
|
||
|
break ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!ok)
|
||
|
{
|
||
|
serialClose (fd) ;
|
||
|
return FALSE ;
|
||
|
}
|
||
|
|
||
|
node = wiringPiNewNode (pinBase, numPins) ;
|
||
|
|
||
|
node->fd = fd ;
|
||
|
node->pinMode = myPinMode ;
|
||
|
node->pullUpDnControl = myPullUpDnControl ;
|
||
|
node->analogRead = myAnalogRead ;
|
||
|
node->digitalRead = myDigitalRead ;
|
||
|
node->digitalWrite = myDigitalWrite ;
|
||
|
node->pwmWrite = myPwmWrite ;
|
||
|
|
||
|
return TRUE ;
|
||
|
}
|