Gordons Projects

--> Projects Top-Level GIT

OK. So the Pi v2 I have had older firmware and it wasn't quite
[wiringPi] / wiringPi / drcSerial.c
1 /*
2  * drcSerial.c:
3  *      Extend wiringPi with the DRC Serial protocol (e.g. to Arduino)
4  *      Copyright (c) 2013 Gordon Henderson
5  ***********************************************************************
6  * This file is part of wiringPi:
7  *      https://projects.drogon.net/raspberry-pi/wiringpi/
8  *
9  *    wiringPi is free software: you can redistribute it and/or modify
10  *    it under the terms of the GNU Lesser General Public License as
11  *    published by the Free Software Foundation, either version 3 of the
12  *    License, or (at your option) any later version.
13  *
14  *    wiringPi is distributed in the hope that it will be useful,
15  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *    GNU Lesser General Public License for more details.
18  *
19  *    You should have received a copy of the GNU Lesser General Public
20  *    License along with wiringPi.
21  *    If not, see <http://www.gnu.org/licenses/>.
22  ***********************************************************************
23  */
24
25 #include <stdio.h>
26 #include <time.h>
27 #include <string.h>
28 #include <errno.h>
29
30 #include "wiringPi.h"
31 #include "wiringSerial.h"
32
33 #include "drcSerial.h"
34
35 #ifndef TRUE
36 #  define       TRUE    (1==1)
37 #  define       FALSE   (1==2)
38 #endif
39
40
41 /*
42  * myPinMode:
43  *      Change the pin mode on the remote DRC device
44  *********************************************************************************
45  */
46
47 static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode)
48 {
49   /**/ if (mode == OUTPUT)
50     serialPutchar (node->fd, 'o') ;       // Input
51   else if (mode == PWM_OUTPUT)
52     serialPutchar (node->fd, 'p') ;       // PWM
53   else
54     serialPutchar (node->fd, 'i') ;       // Default to input
55
56   serialPutchar (node->fd, pin - node->pinBase) ;
57 }
58
59
60 /*
61  * myPullUpDnControl:
62  *      ATmegas only have pull-up's on of off. No pull-downs.
63  *********************************************************************************
64  */
65
66 static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode)
67 {
68
69 // Force pin into input mode
70
71   serialPutchar (node->fd, 'i' ) ;
72   serialPutchar (node->fd, pin - node->pinBase) ;
73
74   /**/ if (mode == PUD_UP)
75   {
76     serialPutchar (node->fd, '1') ;
77     serialPutchar (node->fd, pin - node->pinBase) ;
78   }
79   else if (mode == PUD_OFF)
80   {
81     serialPutchar (node->fd, '0') ;
82     serialPutchar (node->fd, pin - node->pinBase) ;
83   }
84 }
85
86
87 /*
88  * myDigitalWrite:
89  *********************************************************************************
90  */
91
92 static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value)
93 {
94   serialPutchar (node->fd, value == 0 ? '0' : '1') ;
95   serialPutchar (node->fd, pin - node->pinBase) ;
96 }
97
98
99 /*
100  * myPwmWrite:
101  *********************************************************************************
102  */
103
104 static void myPwmWrite (struct wiringPiNodeStruct *node, int pin, int value)
105 {
106   serialPutchar (node->fd, 'v') ;
107   serialPutchar (node->fd, pin - node->pinBase) ;
108   serialPutchar (node->fd, value & 0xFF) ;
109 }
110
111
112 /*
113  * myAnalogRead:
114  *********************************************************************************
115  */
116
117 static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
118 {
119   int vHi, vLo ;
120
121   serialPutchar (node->fd, 'a') ;
122   serialPutchar (node->fd, pin - node->pinBase) ;
123   vHi = serialGetchar (node->fd) ;
124   vLo = serialGetchar (node->fd) ;
125
126   return (vHi << 8) | vLo ;
127 }
128
129
130 /*
131  * myDigitalRead:
132  *********************************************************************************
133  */
134
135 static int myDigitalRead (struct wiringPiNodeStruct *node, int pin)
136 {
137   serialPutchar (node->fd, 'r') ; // Send read command
138   serialPutchar (node->fd, pin - node->pinBase) ;
139   return (serialGetchar (node->fd) == '0') ? 0 : 1 ;
140 }
141
142
143 /*
144  * drcSetup:
145  *      Create a new instance of an DRC GPIO interface.
146  *      Could be a variable nunber of pins here - we might not know in advance
147  *      if it's an ATmega with 14 pins, or something with less or more!
148  *********************************************************************************
149  */
150
151 int drcSetupSerial (const int pinBase, const int numPins, const char *device, const int baud)
152 {
153   int fd ;
154   int ok, tries ;
155   time_t then ;
156   struct wiringPiNodeStruct *node ;
157
158   if ((fd = serialOpen (device, baud)) < 0)
159     return wiringPiFailure (WPI_ALMOST, "Unable to open DRC device (%s): %s", device, strerror (errno)) ;
160
161   delay (10) ;  // May need longer if it's an Uno that reboots on the open...
162
163 // Flush any pending input
164
165   while (serialDataAvail (fd))
166     (void)serialGetchar (fd) ;
167
168   ok = FALSE ;
169   for (tries = 1 ; (tries < 5) && (!ok) ; ++tries)
170   {
171     serialPutchar (fd, '@') ;           // Ping
172     then = time (NULL) + 2 ;
173     while (time (NULL) < then)
174       if (serialDataAvail (fd))
175       {
176         if (serialGetchar (fd) == '@')
177         {
178           ok = TRUE ;
179           break ;
180         }
181       }
182   }
183
184   if (!ok)
185   {
186     serialClose (fd) ;
187     return wiringPiFailure (WPI_FATAL, "Unable to communicate with DRC serial device") ;
188   }
189
190   node = wiringPiNewNode (pinBase, numPins) ;
191
192   node->fd              = fd ;
193   node->pinMode         = myPinMode ;
194   node->pullUpDnControl = myPullUpDnControl ;
195   node->analogRead      = myAnalogRead ;
196   node->digitalRead     = myDigitalRead ;
197   node->digitalWrite    = myDigitalWrite ;
198   node->pwmWrite        = myPwmWrite ;
199
200   return 0 ;
201 }