2626/*
2727 * GPIO pins.
2828 */
29- #define PIN_SWITCH (13 )
29+ #define PIN_SWITCH_NO (12 )
30+ #define PIN_SWITCH_NC (13 )
3031#define PIN_WRLOCK_OUT (14 )
3132#define PIN_WRLOCK_IN (15 )
3233#define PIN_SDA (16 )
@@ -286,12 +287,17 @@ int main(void) {
286287 // Make the I2C pins available to picotool.
287288 bi_decl (bi_2pins_with_func (PIN_SDA, PIN_SCL, GPIO_FUNC_I2C));
288289
289- ::gpio_init (PIN_SWITCH);
290- ::gpio_set_dir (PIN_SWITCH, GPIO_IN);
291- ::gpio_pull_up (PIN_SWITCH);
290+ ::gpio_init (PIN_SWITCH_NO);
291+ ::gpio_set_dir (PIN_SWITCH_NO, GPIO_IN);
292+ ::gpio_pull_up (PIN_SWITCH_NO);
293+ ::gpio_init (PIN_SWITCH_NC);
294+ ::gpio_set_dir (PIN_SWITCH_NC, GPIO_IN);
295+ ::gpio_pull_up (PIN_SWITCH_NC);
292296
293- // Make the lid switch pin available to picotool.
294- bi_decl (bi_1pin_with_name (PIN_SWITCH, " Lid switch (active low)" ));
297+ // Make the lid switch pins available to picotool.
298+ bi_decl (bi_2pins_with_names (
299+ PIN_SWITCH_NO, " Lid switch (active low, normally open)" ,
300+ PIN_SWITCH_NC, " Lid switch (active low, normally closed)" ));
295301
296302 // Load device info and make sure it's valid.
297303 LoadDeviceInfo ();
@@ -305,32 +311,57 @@ int main(void) {
305311
306312 last_pulsecount = pulsecount;
307313
308- static volatile ::absolute_time_t last_edge_time = ::nil_time;
309- static volatile bool switch_state = ::gpio_get (PIN_SWITCH);
314+ static volatile ::absolute_time_t last_edge_time_nc = ::nil_time;
315+ static volatile ::absolute_time_t last_edge_time_no = ::nil_time;
316+ static volatile bool switch_state_nc = ::gpio_get (PIN_SWITCH_NC);
317+ static volatile bool switch_state_no = ::gpio_get (PIN_SWITCH_NO);
318+ // Note: the callback set for the NO pin here also applies to the NC pin, as
319+ // we are using the "easy" IRQ functionality and not actual raw IRQs.
320+ ::gpio_set_irq_enabled (PIN_SWITCH_NC, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE,
321+ true );
310322 ::gpio_set_irq_enabled_with_callback (
311- PIN_SWITCH , GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true ,
312- [](::uint, std::uint32_t ) {
323+ PIN_SWITCH_NO , GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true ,
324+ [](::uint pin , std::uint32_t ) {
313325 const auto now = ::get_absolute_time ();
314326
327+ volatile ::absolute_time_t * p_last_edge_time;
328+ volatile bool * p_switch_state;
329+ bool pulse_count_state;
330+ switch (pin) {
331+ case PIN_SWITCH_NO:
332+ p_last_edge_time = &last_edge_time_no;
333+ p_switch_state = &switch_state_no;
334+ pulse_count_state = true ;
335+ break ;
336+ case PIN_SWITCH_NC:
337+ p_last_edge_time = &last_edge_time_nc;
338+ p_switch_state = &switch_state_nc;
339+ pulse_count_state = false ;
340+ break ;
341+ default :
342+ return ; // ???
343+ }
344+
315345 // This is the first edge seen.
316- if (::is_nil_time (last_edge_time )) [[unlikely]] {
317- last_edge_time = now;
318- switch_state = !switch_state ;
346+ if (::is_nil_time (*p_last_edge_time )) [[unlikely]] {
347+ *p_last_edge_time = now;
348+ *p_switch_state = !*p_switch_state ;
319349 return ;
320350 }
321351
322- const auto delta_t = ::absolute_time_diff_us (last_edge_time , now);
352+ const auto delta_t = ::absolute_time_diff_us (*p_last_edge_time , now);
323353 if (delta_t < SWITCH_DEBOUNCE_TIME_US) {
324354 return ;
325355 }
326356
327- switch_state = !switch_state ;
357+ *p_switch_state = !*p_switch_state ;
328358
329- if (switch_state && delta_t >= MIN_PULSE_WIDTH_US) {
359+ if (*p_switch_state == pulse_count_state &&
360+ delta_t >= MIN_PULSE_WIDTH_US) {
330361 pulsecount = pulsecount + 1 ;
331362 }
332363
333- last_edge_time = now;
364+ *p_last_edge_time = now;
334365 });
335366
336367 char rdbuf[512 ] = {0 };
0 commit comments