Merge branch 'master' of https://github.com/firefields/MCTX3420
[matches/MCTX3420.git] / server / pin_test.c
1 /**
2  * @file pin_test.c
3  * @purpose Implementations to allow direct control over pins through FastCGI
4  */
5
6 #include "pin_test.h"
7
8 #include "bbb_pin.h"
9
10 /**
11  * Export *ALL* pins for control
12  */
13 void Pin_Init()
14 {
15         
16 }
17
18 /**
19  * Unexport all pins
20  */
21 void Pin_Close()
22 {
23         for (int i = 0; i < GPIO_NUM_PINS; ++i)
24                 GPIO_Unexport(g_pin_index_to_gpio[i]);
25
26         for (int i = 0; i < ADC_NUM_PINS; ++i)
27                 ADC_Unexport(i);
28
29         for (int i = 0; i < PWM_NUM_PINS; ++i)
30                 PWM_Unexport(g_pin_safe_pwm[i]);
31 }
32
33 bool Pin_Configure(const char *type, int pin_export, int num)
34 {
35         bool ret = true;
36
37         if (strcmp(type, "gpo") == 0 || strcmp(type, "gpi") == 0)
38         {
39                 if (pin_export < 0)
40                         GPIO_Unexport(num);
41                 else
42                         ret = GPIO_Export(num);
43         }
44         else if (strcmp(type, "pwm") == 0)
45         {
46                 if (pin_export < 0)
47                         PWM_Unexport(num);
48                 else
49                         ret = PWM_Export(num);          
50         }
51         else if (strcmp(type, "adc") == 0)
52         {
53                 if (pin_export < 0)
54                         ADC_Unexport(num);
55                 else
56                         ret = ADC_Export(num);
57         }
58         return ret;
59 }
60
61 /**
62  * Handle a request to the Pin test module
63  * @param context - The FastCGI context
64  * @param params - key/value pair parameters as a string
65  */
66 void Pin_Handler(FCGIContext *context, char * params)
67 {
68         
69         const char * type = NULL;
70         int num = 0;
71         int pin_export = 0;
72         bool set = false;
73         bool pol = false;
74         double freq = 50;
75         double duty = 0.5;
76         
77
78         // key/value pairs
79         FCGIValue values[] = {
80                 {"type", &type, FCGI_REQUIRED(FCGI_STRING_T)},
81                 {"num", &num, FCGI_REQUIRED(FCGI_INT_T)}, 
82                 {"export", &pin_export, FCGI_INT_T},
83                 {"set", &set, FCGI_BOOL_T},
84                 {"pol", &pol, FCGI_BOOL_T},
85                 {"freq", &freq, FCGI_DOUBLE_T},
86                 {"duty", &duty, FCGI_DOUBLE_T}
87         };
88
89         // enum to avoid the use of magic numbers
90         typedef enum {
91                 TYPE,
92                 NUM,
93                 EXPORT,
94                 SET,
95                 POL,
96                 FREQ,
97                 DUTY
98         } SensorParams;
99         
100         // Fill values appropriately
101         if (!FCGI_ParseRequest(context, params, values, sizeof(values)/sizeof(FCGIValue)))
102         {
103                 // Error occured; FCGI_RejectJSON already called
104                 return;
105         }
106
107         Log(LOGDEBUG, "Params: type = %s, num = %d, export = %d, set = %d, pol = %d, freq = %f, duty = %f", type, num, pin_export, set, pol, freq, duty);
108         if (pin_export != 0)
109         {
110                 if (!Pin_Configure(type, pin_export, num))
111                 {
112                         FCGI_RejectJSON(context, "Failed to (un)export the pin. Check that a valid number has been specified.");
113                         return;
114                 }
115                 FCGI_BeginJSON(context, STATUS_OK);
116                 FCGI_JSONPair("description", "Pin (un)export OK!");
117                 FCGI_EndJSON();
118                 return;
119         }
120
121         if (strcmp(type, "gpo") == 0)
122         {
123                 if (num <= 0 || num > GPIO_NUM_PINS)
124                 {
125                         FCGI_RejectJSON(context, "Invalid GPIO pin");
126                         return;
127                 }
128
129                 Log(LOGDEBUG, "Setting GPIO%d to %d", num, set);
130                 if (!GPIO_Set(num, set))
131                 {
132                         FCGI_RejectJSON(context, "Failed to set the GPIO pin. Check that it's exported.");
133                 }
134                 else
135                 {
136                         FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
137                         FCGI_PrintRaw("GPIO%d set to %d\n", num, set);
138                 }
139         }
140         else if (strcmp(type, "gpi") == 0)
141         {
142                 if (num < 0 || num >= GPIO_NUM_PINS)
143                 {
144                         FCGI_RejectJSON(context, "Invalid GPIO pin");
145                         return;
146                 }
147                 Log(LOGDEBUG, "Reading GPIO%d", num);
148                 bool val;
149                 if (!GPIO_Read(num, &val))
150                 {
151                         FCGI_RejectJSON(context, "Failed to read from the GPIO pin. Check that it's exported.");
152                 }
153                 else
154                 {
155                         FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
156                         FCGI_PrintRaw("GPIO%d reads %d\n", num, val);
157                 }
158         }
159         else if (strcmp(type, "adc") == 0)
160         {
161                 if (num < 0 || num >= ADC_NUM_PINS)
162                 {
163                         FCGI_RejectJSON(context, "Invalid ADC pin");
164                         return;
165                 }
166                 Log(LOGDEBUG, "Reading ADC%d", num, set);
167                 int raw_adc;
168                 if (!ADC_Read(num, &raw_adc))
169                 {
170                         FCGI_RejectJSON(context, "ADC read failed. Check that it's exported.");
171                 }
172                 else
173                 {
174                         FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
175                         FCGI_PrintRaw("ADC%d reads %d\n", num, raw_adc);
176                 }
177         }
178         else if (strcmp(type, "pwm") == 0)
179         {
180                 if (num < 0 || num >= PWM_NUM_SAFE_PINS)
181                 {
182                         FCGI_RejectJSON(context, "Invalid PWM pin");
183                         return;
184                 }
185                 
186                 if (set)
187                 {
188                         Log(LOGDEBUG, "Setting PWM%d", num);
189                         duty = duty < 0 ? 0 : duty > 1 ? 1 : duty;
190                         long period_ns = (long)(1e9 / freq);
191                         long duty_ns = (long)(duty * period_ns);
192                         if (!PWM_Set(num, pol, period_ns, duty_ns))
193                         {
194                                 FCGI_RejectJSON(context, "PWM set failed. Check if it's exported, and that there's no channel conflict.");
195                         }
196                         else
197                         {
198                                 FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
199                                 FCGI_PrintRaw("PWM%d set to period_ns = %lu (%f Hz), duty_ns = %lu (%f), polarity = %d", 
200                                         num, period_ns, freq, duty_ns, duty*100, (int)pol);
201                         }
202                 }
203                 else
204                 {
205                         Log(LOGDEBUG, "Stopping PWM%d",num);
206                         PWM_Stop(g_pin_safe_pwm[num]);
207                         FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
208                         FCGI_PrintRaw("PWM%d stopped",num);
209                 }               
210         }
211         else
212         {
213                 Log(LOGDEBUG, "Invalid pin type %s", type);
214                 FCGI_RejectJSON(context, "Invalid pin type");
215         }
216
217 }

UCC git Repository :: git.ucc.asn.au