static void echill_send_wakeup_ind(void){ // update state tx_state = TX_W4_WAKEUP; ehcill_state = EHCILL_STATE_W4_ACK; ehcill_command_to_send = EHCILL_WAKE_UP_IND; hal_uart_dma_send_block(&ehcill_command_to_send, 1); }
static int ehcill_send_packet(uint8_t packet_type, uint8_t *packet, int size){ // check for ongoing write switch (tx_state){ case TX_W4_WAKEUP: case TX_W4_PACKET_SENT: // we should not arrive here, log state log_error("h4_send_packet with tx_state = %u, ehcill_state %u, packet type %u, data %02x %02x %02x", tx_state, ehcill_state, packet_type, packet[0], packet[1], packet[2]); return -1; case TX_IDLE: case TX_DONE: case TX_W2_EHCILL_SEND: case TX_W4_EHCILL_SENT: break; } // store packet type before actual data and increase size size++; packet--; *packet = packet_type; // store request tx_data = packet; tx_len = size; // if awake, just start sending if (!ehcill_sleep_mode_active()){ tx_state = TX_W4_PACKET_SENT; hal_uart_dma_send_block(tx_data, tx_len); return 0; } switch (tx_state){ case TX_W2_EHCILL_SEND: case TX_W4_EHCILL_SENT: // wake up / sleep ack in progress, nothing to do now return 0; case TX_IDLE: case TX_DONE: default: // all clear, prepare for wakeup break; } // UART needed again hal_uart_dma_set_sleep(0); ehcill_reactivate_rx(); // start wakeup echill_send_wakeup_ind(); return 0; }
static void h4_block_sent(void){ switch (tx_state){ case TX_W4_HEADER_SENT: tx_state = TX_W4_PACKET_SENT; // h4 packet type + actual packet hal_uart_dma_send_block(tx_data, tx_len); break; case TX_W4_PACKET_SENT: tx_state = TX_DONE; // trigger run loop embedded_trigger(); break; default: break; } }
// potentially called from ISR context static void h4_block_sent(void){ int command; switch (tx_state){ case TX_W4_PACKET_SENT: // packet fully sent, reset state tx_len = 0; // now, send pending ehcill command if neccessary switch (ehcill_command_to_send){ case EHCILL_GO_TO_SLEEP_ACK: ehcill_sleep_ack_timer_setup(); tx_send_packet_sent = 1; break; case EHCILL_WAKE_UP_IND: tx_state = TX_W4_EHCILL_SENT; // gpio_clear(GPIOB, GPIO_DEBUG_1); hal_uart_dma_send_block(&ehcill_command_to_send, 1); tx_send_packet_sent = 1; break; default: // trigger run loop tx_state = TX_DONE; tx_send_packet_sent = 1; embedded_trigger(); break; } break; case TX_W4_EHCILL_SENT: tx_state = TX_DONE; command = ehcill_command_to_send; ehcill_command_to_send = 0; if (command == EHCILL_GO_TO_SLEEP_ACK) { // UART not needed after EHCILL_GO_TO_SLEEP_ACK was sent hal_uart_dma_set_sleep(1); } if (h4_outgoing_packet_ready()){ // already packet ready? then start wakeup hal_uart_dma_set_sleep(0); ehcill_reactivate_rx(); echill_send_wakeup_ind(); } // trigger run loop embedded_trigger(); break; default: break; } }
static int h4_send_packet(uint8_t packet_type, uint8_t *packet, int size){ // write in progress if (tx_state != TX_IDLE) { log_error("h4_send_packet with tx_state = %u, type %u, data %02x %02x %02x", tx_state, packet_type, packet[0], packet[1], packet[2]); return -1; } tx_packet_type = packet_type; tx_data = packet; tx_len = size; tx_state = TX_W4_HEADER_SENT; hal_uart_dma_send_block(&tx_packet_type, 1); return 0; }
static int h4_send_packet(uint8_t packet_type, uint8_t *packet, int size){ // write in progress if (tx_state != TX_IDLE) { log_error("h4_send_packet with tx_state = %u, type %u, data %02x %02x %02x", tx_state, packet_type, packet[0], packet[1], packet[2]); return -1; } // store packet type before actual data and increase size size++; packet--; *packet = packet_type; tx_state = TX_W4_PACKET_SENT; hal_uart_dma_send_block(packet, size); return 0; }
static void ehcill_schedule_ecill_command(uint8_t command){ ehcill_command_to_send = command; switch (tx_state){ case TX_IDLE: case TX_DONE: if (ehcill_command_to_send == EHCILL_WAKE_UP_ACK){ // send right away tx_state = TX_W4_EHCILL_SENT; hal_uart_dma_send_block(&ehcill_command_to_send, 1); break; } // change state so BTstack cannot send and setup timer tx_state = TX_W2_EHCILL_SEND; ehcill_sleep_ack_timer_setup(); break; default: break; } }
static void ehcill_handle(uint8_t action){ // log_info("ehcill_handle: %x, state %u, defer_rx %u", action, ehcill_state, ehcill_defer_rx_size); switch(ehcill_state){ case EHCILL_STATE_AWAKE: switch(action){ case EHCILL_GO_TO_SLEEP_IND: // 1. set RTS high - already done by BT RX ISR // 2. enable CTS - CTS always enabled ehcill_state = EHCILL_STATE_SLEEP; #ifdef LOG_EHCILL log_info("EHCILL: GO_TO_SLEEP_IND RX"); #endif // gpio_set(GPIOB, GPIO_DEBUG_1); ehcill_schedule_ecill_command(EHCILL_GO_TO_SLEEP_ACK); break; default: break; } break; case EHCILL_STATE_SLEEP: switch(action){ case EHCILL_CTS_SIGNAL: // UART needed again hal_uart_dma_set_sleep(0); // and continue to receive ehcill_reactivate_rx(); break; case EHCILL_WAKE_UP_IND: ehcill_state = EHCILL_STATE_AWAKE; #ifdef LOG_EHCILL log_info("EHCILL: WAKE_UP_IND RX"); #endif ehcill_schedule_ecill_command(EHCILL_WAKE_UP_ACK); break; default: break; } break; case EHCILL_STATE_W4_ACK: switch(action){ case EHCILL_WAKE_UP_IND: case EHCILL_WAKE_UP_ACK: #ifdef LOG_EHCILL log_info("EHCILL: WAKE_UP_IND or ACK"); #endif tx_state = TX_W4_PACKET_SENT; hal_uart_dma_send_block(tx_data, tx_len); ehcill_state = EHCILL_STATE_AWAKE; break; default: break; } break; } }
static void ehcill_sleep_ack_timer_handler(timer_source_t * timer){ tx_state = TX_W4_EHCILL_SENT; hal_uart_dma_send_block(&ehcill_command_to_send, 1); }