/* * drcSerial.c: * Extend wiringPi with the DRC Serial protocol (e.g. to Arduino) * Copyright (c) 2013 Gordon Henderson *********************************************************************** * This file is part of wiringPi: * https://projects.drogon.net/raspberry-pi/wiringpi/ * * wiringPi is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * wiringPi is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with wiringPi. * If not, see . *********************************************************************** */ #include #include #include #include #include "wiringPi.h" #include "wiringSerial.h" #include "drcSerial.h" #ifndef TRUE # define TRUE (1==1) # define FALSE (1==2) #endif /* * 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 wiringPiFailure (WPI_ALMOST, "Unable to open DRC device (%s): %s", device, strerror (errno)) ; 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 wiringPiFailure (WPI_FATAL, "Unable to communicate with DRC serial device") ; } 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 0 ; }