3 * @brief Implementations to allow direct control over pins through FastCGI
11 * Export *ALL* pins for control
23 for (int i = 0; i < GPIO_NUM_PINS; ++i)
24 GPIO_Unexport(g_pin_index_to_gpio[i]);
26 for (int i = 0; i < ADC_NUM_PINS; ++i)
29 for (int i = 0; i < PWM_NUM_PINS; ++i)
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
39 bool Pin_Configure(const char *type, int pin_export, int num)
43 if (strcmp(type, "gpo") == 0 || strcmp(type, "gpi") == 0)
45 //Don't allow unexport of gpio
47 ret = GPIO_Export(num);
49 else if (strcmp(type, "pwm") == 0)
54 ret = PWM_Export(num);
56 else if (strcmp(type, "adc") == 0)
58 //Don't allow unexport of adc
60 ret = ADC_Export(num);
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
70 void Pin_Handler(FCGIContext *context, char * params)
73 const char * type = NULL;
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}
93 // enum to avoid the use of magic numbers
104 // Fill values appropriately
105 if (!FCGI_ParseRequest(context, params, values, sizeof(values)/sizeof(FCGIValue)))
107 // Error occured; FCGI_RejectJSON already called
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);
114 if (!Pin_Configure(type, pin_export, num))
116 FCGI_RejectJSON(context, "Failed to (un)export the pin. Check that a valid number has been specified.");
119 FCGI_BeginJSON(context, STATUS_OK);
120 FCGI_JSONPair("description", "Pin (un)export OK!");
125 if (strcmp(type, "gpo") == 0)
127 if (num <= 0 || num > GPIO_MAX_NUMBER)
129 FCGI_RejectJSON(context, "Invalid GPIO pin");
133 Log(LOGDEBUG, "Setting GPIO%d to %d", num, set);
134 if (!GPIO_Set(num, set))
136 FCGI_RejectJSON(context, "Failed to set the GPIO pin. Check that it's exported.");
140 FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
141 FCGI_PrintRaw("GPIO%d set to %d\n", num, set);
144 else if (strcmp(type, "gpi") == 0)
146 if (num < 0 || num > GPIO_MAX_NUMBER)
148 FCGI_RejectJSON(context, "Invalid GPIO pin");
151 Log(LOGDEBUG, "Reading GPIO%d", num);
153 if (!GPIO_Read(num, &val))
155 FCGI_RejectJSON(context, "Failed to read from the GPIO pin. Check that it's exported.");
159 FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
160 FCGI_PrintRaw("GPIO%d reads %d\n", num, val);
163 else if (strcmp(type, "adc") == 0)
165 if (num < 0 || num >= ADC_NUM_PINS)
167 FCGI_RejectJSON(context, "Invalid ADC pin");
170 Log(LOGDEBUG, "Reading ADC%d", num, set);
172 if (!ADC_Read(num, &raw_adc))
174 FCGI_RejectJSON(context, "ADC read failed. Check that it's exported.");
178 FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
179 FCGI_PrintRaw("%d\n", raw_adc);
182 else if (strcmp(type, "pwm") == 0)
184 if (num < 0 || num >= PWM_NUM_PINS)
186 FCGI_RejectJSON(context, "Invalid PWM pin");
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))
198 FCGI_RejectJSON(context, "PWM set failed. Check if it's exported, and that there's no channel conflict.");
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);
209 Log(LOGDEBUG, "Stopping PWM%d",num);
211 FCGI_PrintRaw("Content-type: text/plain\r\n\r\n");
212 FCGI_PrintRaw("PWM%d stopped",num);
217 Log(LOGDEBUG, "Invalid pin type %s", type);
218 FCGI_RejectJSON(context, "Invalid pin type");