| @@ -164,11 +164,12 @@ struct chaninfo { | |||||
| GPIO_TypeDef *bank; | GPIO_TypeDef *bank; | ||||
| uint16_t pinnum; | uint16_t pinnum; | ||||
| bool init; | bool init; | ||||
| bool invert; | |||||
| } chans[] = { | } 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, }, | [4] = { .bank = GPIOB, .pinnum = GPIO_PIN_8, .init = true, }, | ||||
| }; | }; | ||||
| #define nitems(x) (sizeof(x) / sizeof *(x)) | #define nitems(x) (sizeof(x) / sizeof *(x)) | ||||
| @@ -180,7 +181,8 @@ set_chan(uint32_t chan, bool val) | |||||
| if (chan < nitems(chans)) { | if (chan < nitems(chans)) { | ||||
| ci = chans[chan]; | 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) | procmsg(struct pktbuf inbuf, struct pktbuf *outbuf) | ||||
| { | { | ||||
| uint32_t args[5]; | uint32_t args[5]; | ||||
| @@ -220,6 +285,19 @@ procmsg(struct pktbuf inbuf, struct pktbuf *outbuf) | |||||
| outbuf->pkt[0] = inbuf.pkt[0]; | outbuf->pkt[0] = inbuf.pkt[0]; | ||||
| switch (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: | case CMD_SETUNSET: | ||||
| if (apos == 2) | if (apos == 2) | ||||
| set_chan(args[0], args[1]); | set_chan(args[0], args[1]); | ||||
| @@ -298,6 +376,8 @@ main() | |||||
| //Radio.Rx(0); | //Radio.Rx(0); | ||||
| loop: | loop: | ||||
| process_sched(); | |||||
| BoardLowPowerHandler(); | BoardLowPowerHandler(); | ||||
| if (Radio.IrqProcess != NULL) | if (Radio.IrqProcess != NULL) | ||||
| Radio.IrqProcess(); | Radio.IrqProcess(); | ||||