diff --git a/TinyFrame/TF_Integration.c b/TinyFrame/TF_Integration.c index 1828963..01fd4af 100644 --- a/TinyFrame/TF_Integration.c +++ b/TinyFrame/TF_Integration.c @@ -20,7 +20,7 @@ void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len) #define CHUNK 64 // same as TF_SENDBUF_LEN, so we should always have only one run of the loop int32_t total = (int32_t) len; while (total > 0) { - assert_param(osOK == osSemaphoreWait(semVcomTxReadyHandle, 5000)); + assert_param(osOK == osSemaphoreWait(semVcomTxReadyHandle, 1000)); uint16_t chunksize = (uint16_t) MIN(total, CHUNK); assert_param(USBD_OK == CDC_Transmit_FS((uint8_t *) buff, chunksize)); diff --git a/platform/hw_utils.c b/platform/hw_utils.c index 5c0c9fb..a14c33b 100644 --- a/platform/hw_utils.c +++ b/platform/hw_utils.c @@ -2,14 +2,67 @@ // Created by MightyPork on 2017/11/26. // +#include "platform.h" #include #include "hw_utils.h" #include "macro.h" -#define PINS_COUNT 16 +const uint32_t LL_SYSCFG_EXTI_PORTS[PORTS_COUNT] = { + LL_SYSCFG_EXTI_PORTA, + LL_SYSCFG_EXTI_PORTB, + LL_SYSCFG_EXTI_PORTC, + LL_SYSCFG_EXTI_PORTD, + LL_SYSCFG_EXTI_PORTE, +#if PORTS_COUNT>5 + LL_SYSCFG_EXTI_PORTF, +#endif +#if PORTS_COUNT>6 + LL_SYSCFG_EXTI_PORTG, +#endif +}; + +const uint32_t LL_SYSCFG_EXTI_LINES[16] = { + LL_SYSCFG_EXTI_LINE0, + LL_SYSCFG_EXTI_LINE1, + LL_SYSCFG_EXTI_LINE2, + LL_SYSCFG_EXTI_LINE3, + LL_SYSCFG_EXTI_LINE4, + LL_SYSCFG_EXTI_LINE5, + LL_SYSCFG_EXTI_LINE6, + LL_SYSCFG_EXTI_LINE7, + LL_SYSCFG_EXTI_LINE8, + LL_SYSCFG_EXTI_LINE9, + LL_SYSCFG_EXTI_LINE10, + LL_SYSCFG_EXTI_LINE11, + LL_SYSCFG_EXTI_LINE12, + LL_SYSCFG_EXTI_LINE13, + LL_SYSCFG_EXTI_LINE14, + LL_SYSCFG_EXTI_LINE15, +}; +COMPILER_ASSERT(16 == ELEMENTS_IN_ARRAY(LL_SYSCFG_EXTI_LINES)); + +const uint32_t LL_EXTI_LINES[16] = { + LL_EXTI_LINE_0, + LL_EXTI_LINE_1, + LL_EXTI_LINE_2, + LL_EXTI_LINE_3, + LL_EXTI_LINE_4, + LL_EXTI_LINE_5, + LL_EXTI_LINE_6, + LL_EXTI_LINE_7, + LL_EXTI_LINE_8, + LL_EXTI_LINE_9, + LL_EXTI_LINE_10, + LL_EXTI_LINE_11, + LL_EXTI_LINE_12, + LL_EXTI_LINE_13, + LL_EXTI_LINE_14, + LL_EXTI_LINE_15, +}; +COMPILER_ASSERT(16 == ELEMENTS_IN_ARRAY(LL_EXTI_LINES)); /** Pin number to LL bitfield mapping */ -static const uint32_t ll_pins[PINS_COUNT] = { +const uint32_t LL_GPIO_PINS[16] = { LL_GPIO_PIN_0, LL_GPIO_PIN_1, LL_GPIO_PIN_2, @@ -27,10 +80,10 @@ static const uint32_t ll_pins[PINS_COUNT] = { LL_GPIO_PIN_14, LL_GPIO_PIN_15, }; -COMPILER_ASSERT(16 == ELEMENTS_IN_ARRAY(ll_pins)); +COMPILER_ASSERT(16 == ELEMENTS_IN_ARRAY(LL_GPIO_PINS)); /** Port number (A=0) to config struct pointer mapping */ -static GPIO_TypeDef * const port_periphs[] = { +GPIO_TypeDef * const GPIO_PERIPHS[PORTS_COUNT] = { GPIOA, GPIOB, GPIOC, @@ -43,20 +96,20 @@ static GPIO_TypeDef * const port_periphs[] = { GPIOG, #endif }; -COMPILER_ASSERT(PORTS_COUNT == ELEMENTS_IN_ARRAY(port_periphs)); +COMPILER_ASSERT(PORTS_COUNT == ELEMENTS_IN_ARRAY(GPIO_PERIPHS)); /** Convert pin number to LL bitfield */ uint32_t hw_pin2ll(uint8_t pin_number, bool *suc) { assert_param(suc != NULL); - if(pin_number >= PINS_COUNT) { + if(pin_number > 15) { dbg("Bad pin: %d", pin_number); // TODO proper report *suc = false; return 0; } - return ll_pins[pin_number]; + return LL_GPIO_PINS[pin_number]; } /** Convert port name (A,B,C...) to peripheral struct pointer */ @@ -71,7 +124,7 @@ GPIO_TypeDef *hw_port2periph(char port_name, bool *suc) } uint8_t num = (uint8_t) (port_name - 'A'); - return port_periphs[num]; + return GPIO_PERIPHS[num]; } /** Convert a pin to resource handle */ @@ -85,7 +138,7 @@ Resource hw_pin2resource(char port_name, uint8_t pin_number, bool *suc) return R_NONE; } - if(pin_number >= PINS_COUNT) { + if(pin_number > 15) { dbg("Bad pin: %d", pin_number); // TODO proper report *suc = false; return R_NONE; @@ -261,14 +314,27 @@ uint16_t pinmask_pack(uint16_t spread, uint16_t mask) return result; } +/** Convert spread port pin number to a packed index using a mask */ +uint8_t pinmask_translate(uint16_t mask, uint8_t index) +{ + int cnt = 0; + for (int i = 0; i<16; i++) { + if (mask & (1<resources, rsc)) { rsc_dbg("Freeing pin %s", rsc_get_name((Resource)rsc)); - GPIO_TypeDef *port = port_periphs[(rsc-R_PA0) / 16]; - uint32_t ll_pin = ll_pins[(rsc-R_PA0)%16]; + GPIO_TypeDef *port = GPIO_PERIPHS[(rsc-R_PA0) / 16]; + uint32_t ll_pin = LL_GPIO_PINS[(rsc-R_PA0)%16]; LL_GPIO_SetPinMode(port, ll_pin, LL_GPIO_MODE_ANALOG); } } diff --git a/platform/hw_utils.h b/platform/hw_utils.h index 678ca14..15baecd 100644 --- a/platform/hw_utils.h +++ b/platform/hw_utils.h @@ -11,6 +11,12 @@ #include "platform.h" #include "resources.h" +extern const uint32_t LL_SYSCFG_EXTI_PORTS[PORTS_COUNT]; +extern const uint32_t LL_SYSCFG_EXTI_LINES[16]; +extern GPIO_TypeDef * const GPIO_PERIPHS[PORTS_COUNT]; +extern const uint32_t LL_GPIO_PINS[16]; +extern const uint32_t LL_EXTI_LINES[16]; + /** * Convert pin number to LL driver bitfield for working with the pin. * @@ -97,6 +103,13 @@ uint16_t pinmask_spread(uint16_t packed, uint16_t mask); */ uint16_t pinmask_pack(uint16_t spread, uint16_t mask); +/** + * Convert spread port pin number to a packed index using a mask + * + * eg. with a mask 0b1010 and index 3, the result is 1 (bit 1 of the packed - 0bX0) + */ +uint8_t pinmask_translate(uint16_t mask, uint8_t index); + /** * Set all GPIO resources held by unit to analog. * This is a part of unit teardown. diff --git a/platform/irq_dispatcher.c b/platform/irq_dispatcher.c index 6935efe..ee87364 100644 --- a/platform/irq_dispatcher.c +++ b/platform/irq_dispatcher.c @@ -2,9 +2,29 @@ // Created by MightyPork on 2018/01/14. // -#include #include "platform.h" #include "irq_dispatcher.h" +#include "hw_utils.h" + +void * const EXTIS[16] = { + // dumym values for easier debug - those are used instead of periph addresses because EXTIs have no dedicated periph control blocks + (void *const) 0x9000, + (void *const) 0x9001, + (void *const) 0x9002, + (void *const) 0x9003, + (void *const) 0x9004, + (void *const) 0x9005, + (void *const) 0x9006, + (void *const) 0x9007, + (void *const) 0x9008, + (void *const) 0x9009, + (void *const) 0x900A, + (void *const) 0x900B, + (void *const) 0x900C, + (void *const) 0x900D, + (void *const) 0x900E, + (void *const) 0x900F, +}; struct cbslot { IrqCallback callback; @@ -12,6 +32,8 @@ struct cbslot { }; static struct callbacks_ { + struct cbslot exti[16]; + struct cbslot usart1; struct cbslot usart2; struct cbslot usart3; @@ -51,9 +73,9 @@ void irqd_init(void) // NVIC_EnableIRQ(RTC_IRQn); /*!< RTC Interrupt through EXTI Lines 17, 19 and 20 */ // NVIC_EnableIRQ(FLASH_IRQn); /*!< FLASH global Interrupt */ // NVIC_EnableIRQ(RCC_CRS_IRQn); /*!< RCC & CRS global Interrupt */ -// NVIC_EnableIRQ(EXTI0_1_IRQn); /*!< EXTI Line 0 and 1 Interrupt */ -// NVIC_EnableIRQ(EXTI2_3_IRQn); /*!< EXTI Line 2 and 3 Interrupt */ -// NVIC_EnableIRQ(EXTI4_15_IRQn); /*!< EXTI Line 4 to 15 Interrupt */ + NVIC_EnableIRQ(EXTI0_1_IRQn); /*!< EXTI Line 0 and 1 Interrupt */ + NVIC_EnableIRQ(EXTI2_3_IRQn); /*!< EXTI Line 2 and 3 Interrupt */ + NVIC_EnableIRQ(EXTI4_15_IRQn); /*!< EXTI Line 4 to 15 Interrupt */ // NVIC_EnableIRQ(TSC_IRQn); /*!< Touch Sensing Controller Interrupts */ NVIC_EnableIRQ(DMA1_Channel1_IRQn); /*!< DMA1 Channel 1 Interrupt */ NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); /*!< DMA1 Channel 2 and Channel 3 Interrupt */ @@ -107,6 +129,10 @@ static struct cbslot *get_slot_for_periph(void *periph) else if (periph == USART5) slot = &callbacks.usart5; #endif + else if (periph >= EXTIS[0] && periph <= EXTIS[15]) { + slot = &callbacks.exti[periph - EXTIS[0]]; + } + // --- DMA1 --- else if (periph == DMA1_Channel1) slot = &callbacks.dma1_1; else if (periph == DMA1_Channel2) slot = &callbacks.dma1_2; @@ -154,12 +180,16 @@ void irqd_attach(void *periph, IrqCallback callback, void *arg) slot->arg = arg; } -void irqd_detach(void *periph, IrqCallback callback) +void* irqd_detach(void *periph, IrqCallback callback) { + void *oldArg = NULL; struct cbslot *slot = get_slot_for_periph(periph); if (slot->callback == callback) { + oldArg = slot->arg; slot->callback = NULL; slot->arg = NULL; + + return oldArg; } else { trap("Detach IRQ %p() from %p but %p() bound instead", callback, periph, slot->callback); } @@ -167,6 +197,8 @@ void irqd_detach(void *periph, IrqCallback callback) #define CALL_IRQ_HANDLER(slot) do { if (slot.callback) slot.callback(slot.arg); } while (0) +// ------------ USARTS ------------ + void USART1_IRQHandler(void) { CALL_IRQ_HANDLER(callbacks.usart1); @@ -177,32 +209,6 @@ void USART2_IRQHandler(void) CALL_IRQ_HANDLER(callbacks.usart2); } -#if 0 -static bool usart_check_irq(USART_TypeDef *USARTx) -{ - uint32_t isrflags = USARTx->ISR; - uint32_t cr1its = USARTx->CR1; - uint32_t cr2its = USARTx->CR2; - uint32_t cr3its = USARTx->CR3; - - if ((cr1its & USART_CR1_RTOIE) && (isrflags & USART_ISR_RTOF)) return true; - if ((cr1its & USART_CR1_RXNEIE) && (isrflags & USART_ISR_RXNE)) return true; - if ((cr1its & USART_CR1_TCIE) && (isrflags & USART_ISR_TC)) return true; - if ((cr1its & USART_CR1_TXEIE) && (isrflags & USART_ISR_TXE)) return true; - if ((cr3its & USART_CR3_EIE) && (isrflags & (USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE))) return true; - - if ((cr1its & USART_CR1_IDLEIE) && (isrflags & USART_ISR_IDLE)) return true; - if ((cr1its & USART_CR1_PEIE) && (isrflags & USART_ISR_PE)) return true; - if ((cr1its & USART_CR1_CMIE) && (isrflags & USART_ISR_CMF)) return true; - if ((cr1its & USART_CR1_EOBIE) && (isrflags & USART_ISR_EOBF)) return true; - if ((cr2its & USART_CR2_LBDIE) && (isrflags & USART_ISR_LBDF)) return true; - if ((cr3its & USART_CR3_CTSIE) && (isrflags & USART_ISR_CTS)) return true; - if ((cr3its & USART_CR3_WUFIE) && (isrflags & USART_ISR_WUF)) return true; - - return false; -} -#endif - void USART3_4_IRQHandler(void) { // we won't check the flags here, both can be pending and it's better to let the handler deal with it @@ -210,6 +216,8 @@ void USART3_4_IRQHandler(void) CALL_IRQ_HANDLER(callbacks.usart4); } +// ------------ DMA -------------- + void DMA1_Channel1_IRQHandler(void) { CALL_IRQ_HANDLER(callbacks.dma1_1); @@ -229,43 +237,57 @@ void DMA1_Channel4_5_6_7_IRQHandler(void) if (LL_DMA_IsActiveFlag_GI7(DMA1)) CALL_IRQ_HANDLER(callbacks.dma1_7); } -#if 0 -void WWDG_IRQHandler(void) +// ------------ EXTI ------------ + +static void fire_exti_cb(uint8_t start, uint8_t end) { - // + for (int i = start; i <= end; i++) { + if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINES[i])) { + CALL_IRQ_HANDLER(callbacks.exti[i]); + } + } } -void PVD_VDDIO2_IRQHandler(void) +void EXTI0_1_IRQHandler(void) { - // + fire_exti_cb(0, 1); } -void RTC_IRQHandler(void) +void EXTI2_3_IRQHandler(void) { - // + fire_exti_cb(2, 3); } -void FLASH_IRQHandler(void) +void EXTI4_15_IRQHandler(void) +{ + fire_exti_cb(4, 15); +} + + +// other ISRs... + +#if 0 +void WWDG_IRQHandler(void) { // } -void RCC_CRS_IRQHandler(void) +void PVD_VDDIO2_IRQHandler(void) { // } -void EXTI0_1_IRQHandler(void) +void RTC_IRQHandler(void) { // } -void EXTI2_3_IRQHandler(void) +void FLASH_IRQHandler(void) { // } -void EXTI4_15_IRQHandler(void) +void RCC_CRS_IRQHandler(void) { // } diff --git a/platform/irq_dispatcher.h b/platform/irq_dispatcher.h index e278998..9a6ebc0 100644 --- a/platform/irq_dispatcher.h +++ b/platform/irq_dispatcher.h @@ -7,6 +7,9 @@ #ifndef GEX_F072_IRQ_DISPATCHER_H #define GEX_F072_IRQ_DISPATCHER_H +// Dummy peripherals for use with the +extern void * const EXTIS[16]; + /** * Initialize the interrupt dispatcher */ @@ -35,7 +38,8 @@ void irqd_attach(void *periph, IrqCallback callback, void *data); * * @param periph - peripheral we're attaching to * @param callback - callback to remove, if it doesn't match, do nothing + * @return the arg, if any */ -void irqd_detach(void *periph, IrqCallback callback); +void* irqd_detach(void *periph, IrqCallback callback); #endif //GEX_F072_IRQ_DISPATCHER_H diff --git a/platform/plat_compat.h b/platform/plat_compat.h index 2ef70c4..bd6d7b3 100644 --- a/platform/plat_compat.h +++ b/platform/plat_compat.h @@ -24,7 +24,7 @@ #define FLASH_SAVE_BUF_LEN 128 // Malloc'd buffer for saving to flash #define MSG_QUE_SLOT_SIZE 64 // FIXME this should be possible to lower, but there's some bug with bulk transfer / INI parser -#define RX_QUE_CAPACITY 8 // TinyFrame rx queue size (64 bytes each) +#define RX_QUE_CAPACITY 16 // TinyFrame rx queue size (64 bytes each) #define TF_MAX_PAYLOAD_RX 512 // TF max Rx payload #define TF_SENDBUF_LEN 64 // TF transmit buffer (can be less than a full frame) diff --git a/tasks/sched_queue.h b/tasks/sched_queue.h index e9aa118..ec4ebdd 100644 --- a/tasks/sched_queue.h +++ b/tasks/sched_queue.h @@ -30,10 +30,12 @@ struct sched_que_item { union { TF_ID frame_id; // typically used to pass frame id to the callback void *data1; // arbitrary pointer or int + uint32_t d32_1; // passing a number }; /** Data word 2 */ union { uint32_t d32; // passing a number + uint32_t d32_2; // passing a number uint8_t *buf; // uchar buffer const uint8_t *cbuf; // const uchar buffer const char *str; // string @@ -43,6 +45,7 @@ struct sched_que_item { union { uint32_t len; // typically length of the buffer void *data3; // arbitrary pointer + uint32_t d32_3; // passing a number }; }; diff --git a/tasks/task_msg.c b/tasks/task_msg.c index 510ef9e..3ceaf71 100644 --- a/tasks/task_msg.c +++ b/tasks/task_msg.c @@ -17,11 +17,12 @@ static void que_safe_post(struct rx_sched_combined_que_item *slot) if (inIRQ()) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; assert_param(pdPASS == xQueueSendFromISR(queMsgJobHandle, slot, &xHigherPriorityTaskWoken)); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); #if USE_STACK_MONITOR count = (uint32_t) uxQueueMessagesWaitingFromISR(queMsgJobHandle); #endif + + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } else { assert_param(pdPASS == xQueueSend(queMsgJobHandle, slot, MSG_QUE_POST_TIMEOUT)); diff --git a/units/digital_in/unit_din.c b/units/digital_in/unit_din.c index d4df042..f279700 100644 --- a/units/digital_in/unit_din.c +++ b/units/digital_in/unit_din.c @@ -2,10 +2,12 @@ // Created by MightyPork on 2017/11/25. // -#include -#include "comm/messages.h" #include "unit_base.h" +#include "utils/avrlibc.h" +#include "platform/irq_dispatcher.h" +#include "comm/messages.h" #include "unit_din.h" +#include "tasks/task_msg.h" /** Private data structure */ struct priv { @@ -13,7 +15,11 @@ struct priv { uint16_t pins; // pin mask uint16_t pulldown; // pull-downs (default is pull-up) uint16_t pullup; // pull-ups + uint16_t trig_rise; + uint16_t trig_fall; + uint16_t trig_holdoff; // ms + uint16_t holdoff_countdowns[16]; GPIO_TypeDef *port; }; @@ -32,7 +38,11 @@ static void DI_loadBinary(Unit *unit, PayloadParser *pp) priv->pulldown = pp_u16(pp); priv->pullup = pp_u16(pp); - dbg("load bin, pulldown = %X", priv->pulldown); + if (version >= 1) { + priv->trig_rise = pp_u16(pp); + priv->trig_fall = pp_u16(pp); + priv->trig_holdoff = pp_u16(pp); + } } /** Write to a binary buffer for storing in Flash */ @@ -40,12 +50,15 @@ static void DI_writeBinary(Unit *unit, PayloadBuilder *pb) { struct priv *priv = unit->data; - pb_u8(pb, 0); // version + pb_u8(pb, 1); // version pb_char(pb, priv->port_name); pb_u16(pb, priv->pins); pb_u16(pb, priv->pulldown); pb_u16(pb, priv->pullup); + pb_u16(pb, priv->trig_rise); + pb_u16(pb, priv->trig_fall); + pb_u16(pb, priv->trig_holdoff); } // ------------------------------------------------------------------------ @@ -68,6 +81,15 @@ static error_t DI_loadIni(Unit *unit, const char *key, const char *value) else if (streq(key, "pull-down")) { priv->pulldown = parse_pinmask(value, &suc); } + else if (streq(key, "trig-rise")) { + priv->trig_rise = parse_pinmask(value, &suc); + } + else if (streq(key, "trig-fall")) { + priv->trig_fall = parse_pinmask(value, &suc); + } + else if (streq(key, "trig-hold-off")) { + priv->trig_holdoff = (uint16_t) avr_atoi(value); + } else { return E_BAD_KEY; } @@ -93,6 +115,15 @@ static void DI_writeIni(Unit *unit, IniWriter *iw) iw_comment(iw, "Pins with pull-down"); iw_entry(iw, "pull-down", "%s", pinmask2str(priv->pulldown, unit_tmp512)); + iw_comment(iw, "Trigger pins activated by rising edge"); + iw_entry(iw, "trig-rise", "%s", pinmask2str(priv->trig_rise, unit_tmp512)); + + iw_comment(iw, "Trigger pins activated by falling edge"); + iw_entry(iw, "trig-fall", "%s", pinmask2str(priv->trig_fall, unit_tmp512)); + + iw_comment(iw, "Trigger hold-off time (ms)"); + iw_entry(iw, "trig-hold-off", "%d", (int)priv->trig_holdoff); + #if PLAT_NO_FLOATING_INPUTS iw_comment(iw, "NOTE: Pins use pull-up by default.\r\n"); #endif @@ -112,9 +143,60 @@ static error_t DI_preInit(Unit *unit) priv->pulldown = 0x0000; priv->pullup = 0x0000; + priv->trig_rise = 0x0000; + priv->trig_fall = 0x0000; + priv->trig_holdoff = 20; + return E_SUCCESS; } +static void ID_SendTriggerReportToMaster(Job *job) +{ + Unit *unit = job->data1; + + PayloadBuilder pb = pb_start(unit_tmp512, UNIT_TMP_LEN, NULL); + pb_u8(&pb, unit->callsign); + pb_u8(&pb, 0x00); // report type "Trigger" + pb_u16(&pb, (uint16_t) job->d32_2); // packed, 1 on the triggering pin + pb_u16(&pb, (uint16_t) job->d32_3); // + assert_param(pb.ok); + com_send_pb(MSG_UNIT_REPORT, &pb); +} + +static void DI_handleExti(void *arg) +{ + Unit *unit = arg; + struct priv *priv = unit->data; + uint16_t snapshot = (uint16_t) priv->port->IDR; + + uint16_t trigger_map = 0; + + uint16_t mask = 1; + for (int i = 0; i < 16; i++, mask <<= 1) { + if ((priv->trig_rise|priv->trig_fall) & mask) { + if (LL_EXTI_ReadFlag_0_31(LL_EXTI_LINES[i])) { + if (priv->holdoff_countdowns[i] == 0) { + trigger_map |= 1<holdoff_countdowns[i] = priv->trig_holdoff; + } + + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINES[i]); + } + } + } + + // FIXME the job is not correctly handled, somehow. queue fills but is not collected + if (trigger_map != 0) { + Job j = { + .data1 = unit, + .d32_2 = pinmask_pack(trigger_map, priv->pins), + .d32_3 = snapshot, + .cb = ID_SendTriggerReportToMaster + }; + scheduleJob(&j); + } +} + /** Finalize unit set-up */ static error_t DI_init(Unit *unit) { @@ -150,9 +232,29 @@ static error_t DI_init(Unit *unit) if (priv->pulldown & mask) pull = LL_GPIO_PULL_DOWN; if (priv->pullup & mask) pull = LL_GPIO_PULL_UP; LL_GPIO_SetPinPull(priv->port, ll_pin, pull); + + if ((priv->trig_rise|priv->trig_fall) & mask) { + LL_EXTI_EnableIT_0_31(LL_EXTI_LINES[i]); + + if (priv->trig_rise & mask) { + LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINES[i]); + } + if (priv->trig_fall & mask) { + LL_EXTI_EnableFallingTrig_0_31(LL_EXTI_LINES[i]); + } + + LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTS[priv->port_name-'A'], LL_SYSCFG_EXTI_LINES[i]); + + irqd_attach(EXTIS[i], DI_handleExti, unit); + } } } + // request ticks if we have triggers + if (priv->trig_rise|priv->trig_fall) { + unit->tick_interval = 1; + } + return E_SUCCESS; } @@ -160,8 +262,23 @@ static error_t DI_init(Unit *unit) /** Tear down the unit */ static void DI_deInit(Unit *unit) { + struct priv *priv = unit->data; + // pins are de-inited during teardown + if (unit->status == E_SUCCESS) { + // Detach EXTI handlers and disable interrupts + if (priv->trig_rise | priv->trig_fall) { + uint16_t mask = 1; + for (int i = 0; i < 16; i++, mask <<= 1) { + if ((priv->trig_rise | priv->trig_fall) & mask) { + LL_EXTI_DisableIT_0_31(LL_EXTI_LINES[i]); + irqd_detach(EXTIS[i], DI_handleExti); + } + } + } + } + // Release all resources rsc_teardown(unit); @@ -203,6 +320,22 @@ static error_t DI_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Pay } } +/** + * Decrement all the hold-off timers on tick + * + * @param unit + */ +static void DI_updateTick(Unit *unit) +{ + struct priv *priv = unit->data; + + for (int i = 0; i < 16; i++) { + if (priv->holdoff_countdowns[i] > 0) { + priv->holdoff_countdowns[i]--; + } + } +} + // ------------------------------------------------------------------------ /** Unit template */ @@ -220,4 +353,5 @@ const UnitDriver UNIT_DIN = { .deInit = DI_deInit, // Function .handleRequest = DI_handleRequest, + .updateTick = DI_updateTick, }; diff --git a/units/usart/unit_usart.c b/units/usart/unit_usart.c index 40983fc..f5f2d00 100644 --- a/units/usart/unit_usart.c +++ b/units/usart/unit_usart.c @@ -19,7 +19,8 @@ static void UUSART_SendReceivedDataToMaster(Job *job) uint32_t readpos = job->d32; uint32_t count = job->len; - // TODO modify TF to allow writing in multiple chunks to avoid this useless buffer copying + // TODO use TF's Multipart sending + // TODO add API for building reports PayloadBuilder pb = pb_start(unit_tmp512, UNIT_TMP_LEN, NULL); pb_u8(&pb, unit->callsign); pb_u8(&pb, 0x00); // report type "Data received"