int main() { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE); Usart1Init(); SysTick_Config(SystemCoreClock / 100); setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); while(1) { printk("Hello world\n\r"); sleep_ticks(1000); } }
bool send_text(const char* msg, bool is_flash, bool wait_for_finish) { /* #ifdef DBGPRINT // This needs an explanation: I am using the AVR Dragon to flash the keyboard firmware // and it looks like the dragon has a strong pullup on the MISO line. This pullup is // stronger than the nRF24L01+ MISO output driver, so if the programming ISP cable is plugged in // it keeps MISO high all the time, and I can't read anything from the nRF24L01+ and the send_text() // function will never return. // // So, instead of plugging the ISP cable in and out all the time while testing firmware updates, // we just output the text to UART and return if (is_flash) dprint_P(msg); else dprint(msg); _delay_ms(1); return true; #endif // I'm not using the AVR Dragon any more :) */ // this message id is used to avoid presenting the same package to the dongle in case dongle // received the message, but the keyboard did not receive the ACK static uint8_t msg_id = 1; rf_msg_text_t txt_msg; txt_msg.msg_type = MT_TEXT; // send the message in chunks of MAX_TEXT_LEN uint16_t msglen = is_flash ? strlen_P(msg) : strlen(msg); uint8_t chunklen, msg_bytes_free; while (msglen) { // flush the ACK payload rf_ctrl_process_ack_payloads(&msg_bytes_free, NULL); // copy a chunk of the message chunklen = msglen > MAX_TEXT_LEN ? MAX_TEXT_LEN : msglen; if (is_flash) memcpy_P(txt_msg.text, msg, chunklen); else memcpy(txt_msg.text, msg, chunklen); msglen -= chunklen; msg += chunklen; // query the free space of the buffer on the dongle to see if // it is large enough to store the next chunk for (;;) { // send an empty text message; this causes the dongle to respond with ACK payload // that contains the number of bytes available in the dongle's text buffer if (!rf_ctrl_send_message(&txt_msg, 2)) // 1 byte for the message type ID, 1 for the msg_id return false; rf_ctrl_process_ack_payloads(&msg_bytes_free, NULL); // enough space in the dongle buffer? if (msg_bytes_free > chunklen + 1) break; sleep_ticks(40); // doze off a little; roughly 10ms } // set the message id and send it on it's way msg_id = msg_id == 0xff ? 1 : msg_id + 1; txt_msg.msg_id = msg_id; if (!rf_ctrl_send_message(&txt_msg, chunklen + 2)) return false; } // flush the ACK payload(s) rf_ctrl_process_ack_payloads(NULL, NULL); // wait for the buffer on the dongle to become empty // this will ensure that all the keystrokes are sent to the host and that subsequent // keystrokes we're sending won't mess up the text we want output at the host if (wait_for_finish) { uint8_t msg_bytes_capacity = 0; do { if (!rf_ctrl_send_message(&txt_msg, 2)) return false; rf_ctrl_process_ack_payloads(&msg_bytes_free, &msg_bytes_capacity); } while (msg_bytes_free == 0 || msg_bytes_free != msg_bytes_capacity); } return true; }
bool rf_ctrl_send_message(const void* buff, const uint8_t num_bytes) { nRF_WriteReg(RF_SETUP, vRF_DR_2MBPS // data rate | get_nrf_output_power()); // output power nRF_FlushTX(); nRF_WriteReg(CONFIG, vEN_CRC | vCRCO | vPWR_UP); // power up nRF_WriteReg(STATUS, vTX_DS | vRX_DR | vMAX_RT); // reset the status flag nRF_WriteTxPayload(buff, num_bytes); bool is_sent; uint8_t attempts = 0; const uint8_t MAX_ATTEMPTS = 45; uint8_t ticks = 15; const uint8_t TICKS_INCREMENT = 20; do { nRF_CE_hi(); // signal the transceiver to send the packet // wait for the nRF to signal an event sleep_ticks(3); while (PIN(NRF_IRQ_PORT) & _BV(NRF_IRQ_BIT)) sleep_ticks(1); nRF_CE_lo(); uint8_t status = nRF_NOP(); // read the status reg is_sent = (status & vTX_DS) != 0; // did we get an ACK? nRF_WriteReg(STATUS, vMAX_RT | vTX_DS | vRX_DR); // reset the status flags // read the ARC nRF_ReadReg(OBSERVE_TX); arc_total += nRF_data[1] & 0x0f; ++rf_packets_total; if (!is_sent) { ++plos_total; nRF_ReuseTxPayload(); // send the last message again if (ticks >= 0xfe - TICKS_INCREMENT) { sleep_max(5); // 63ms*5 == 0.315sec } else { sleep_ticks(ticks); ticks += TICKS_INCREMENT; } } ++attempts; } while (!is_sent && attempts < MAX_ATTEMPTS); nRF_WriteReg(CONFIG, vEN_CRC | vCRCO); // nRF power down return is_sent; }