| @@ -164,11 +164,12 @@ struct chaninfo { | |||
| GPIO_TypeDef *bank; | |||
| uint16_t pinnum; | |||
| bool init; | |||
| bool invert; | |||
| } chans[] = { | |||
| [0] = { .bank = GPIOB, .pinnum = GPIO_PIN_5, .init = true, }, | |||
| [1] = { .bank = GPIOB, .pinnum = GPIO_PIN_6, .init = true, }, | |||
| [2] = { .bank = GPIOB, .pinnum = GPIO_PIN_7, .init = true, }, | |||
| [3] = { .bank = GPIOB, .pinnum = GPIO_PIN_9, .init = true, }, | |||
| [0] = { .bank = GPIOB, .pinnum = GPIO_PIN_5, .init = true, .invert = true, }, | |||
| [1] = { .bank = GPIOB, .pinnum = GPIO_PIN_6, .init = true, .invert = true, }, | |||
| [2] = { .bank = GPIOB, .pinnum = GPIO_PIN_7, .init = true, .invert = true, }, | |||
| [3] = { .bank = GPIOB, .pinnum = GPIO_PIN_9, .init = true, .invert = true, }, | |||
| [4] = { .bank = GPIOB, .pinnum = GPIO_PIN_8, .init = true, }, | |||
| }; | |||
| #define nitems(x) (sizeof(x) / sizeof *(x)) | |||
| @@ -180,7 +181,8 @@ set_chan(uint32_t chan, bool val) | |||
| if (chan < nitems(chans)) { | |||
| ci = chans[chan]; | |||
| HAL_GPIO_WritePin(ci.bank, ci.pinnum, val ? GPIO_PIN_SET : GPIO_PIN_RESET); | |||
| HAL_GPIO_WritePin(ci.bank, ci.pinnum, val ^ ci.invert ? | |||
| GPIO_PIN_SET : GPIO_PIN_RESET); | |||
| } | |||
| } | |||
| @@ -202,7 +204,70 @@ setup_gpio() | |||
| } | |||
| } | |||
| void | |||
| static struct sched { | |||
| uint32_t cmd; | |||
| uint32_t end_wait_tick; /* end if running, otherwise how long to wait */ | |||
| uint32_t chan; | |||
| } schedule[20]; | |||
| static int schedpos; /* position in schedule, % nitems(schedule)*/ | |||
| static int schedcnt; /* total items waiting */ | |||
| #define SCHED_HEAD (schedule[(schedpos) % nitems(schedule)]) | |||
| #define SCHED_TAIL (schedule[(schedpos + schedcnt) % nitems(schedule)]) | |||
| static void | |||
| start_sched(struct sched *sched) | |||
| { | |||
| sched->end_wait_tick += uwTick; | |||
| if (sched->cmd == CMD_RUNFOR) | |||
| set_chan(sched->chan, 1); | |||
| } | |||
| static void | |||
| process_sched() | |||
| { | |||
| /* nothing to do? */ | |||
| if (schedcnt == 0) | |||
| return; | |||
| /* not yet expired */ | |||
| if (uwTick < SCHED_HEAD.end_wait_tick) | |||
| return; | |||
| if (SCHED_HEAD.cmd == CMD_RUNFOR) | |||
| set_chan(SCHED_HEAD.chan, 0); | |||
| /* we are done, advance */ | |||
| schedpos++; | |||
| schedcnt--; | |||
| if (schedcnt) | |||
| start_sched(&SCHED_HEAD); | |||
| } | |||
| static void | |||
| enqueue_sched(uint32_t cmd, uint32_t ticks, uint32_t chan) | |||
| { | |||
| if (schedcnt >= nitems(schedule)) | |||
| return; | |||
| SCHED_TAIL = (struct sched){ | |||
| .cmd = cmd, | |||
| .end_wait_tick = ticks, | |||
| .chan = chan, | |||
| }; | |||
| if (schedcnt == 0) | |||
| start_sched(&SCHED_HEAD); | |||
| schedcnt++; | |||
| } | |||
| static void | |||
| procmsg(struct pktbuf inbuf, struct pktbuf *outbuf) | |||
| { | |||
| uint32_t args[5]; | |||
| @@ -220,6 +285,19 @@ procmsg(struct pktbuf inbuf, struct pktbuf *outbuf) | |||
| outbuf->pkt[0] = inbuf.pkt[0]; | |||
| switch (inbuf.pkt[0]) { | |||
| case CMD_WAITFOR: | |||
| if (apos == 1) | |||
| enqueue_sched(CMD_WAITFOR, args[0], -1); | |||
| break; | |||
| case CMD_RUNFOR: | |||
| if (apos == 2) | |||
| enqueue_sched(CMD_RUNFOR, args[0], args[1]); | |||
| break; | |||
| case CMD_PING: | |||
| break; | |||
| case CMD_SETUNSET: | |||
| if (apos == 2) | |||
| set_chan(args[0], args[1]); | |||
| @@ -298,6 +376,8 @@ main() | |||
| //Radio.Rx(0); | |||
| loop: | |||
| process_sched(); | |||
| BoardLowPowerHandler(); | |||
| if (Radio.IrqProcess != NULL) | |||
| Radio.IrqProcess(); | |||