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

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