diff --git a/src/main.c b/src/zh_avr_touch_pad.c similarity index 62% rename from src/main.c rename to src/zh_avr_touch_pad.c index 731bf23..79ebc0f 100644 --- a/src/main.c +++ b/src/zh_avr_touch_pad.c @@ -95,23 +95,23 @@ * * @return Stored device id, or DEVICE_ID_UNASSIGNED if none is stored */ -static uint8_t zh_load_device_id(void); +static uint8_t _zh_load_device_id(void); /** * @brief Save the device identifier to EEPROM. * * @param id Device identifier to store */ -static void zh_save_device_id(uint8_t id); +static void _zh_save_device_id(uint8_t id); /** * @brief Initialize INT1 external interrupt for the touch-pad wake-up signal. * * Configures PD3 as a rising-edge triggered external interrupt source and - * enables the INT1 interrupt mask bit. The ISR sets the send_request flag + * enables the INT1 interrupt mask bit. The ISR sets the _send_request flag * to trigger a radio transmission from the main loop. */ -static void zh_pad_interrupt_init(void); +static void _zh_pad_interrupt_init(void); /** * @brief Initialize the hardware SPI peripheral in master mode. @@ -119,7 +119,7 @@ static void zh_pad_interrupt_init(void); * Configures MOSI, SCK and SS pins as outputs, drives SS high, and enables * SPI with Fosc/16 clock rate. */ -static void zh_spi_init(void); +static void _zh_spi_init(void); /** * @brief Perform a single full-duplex SPI byte transfer. @@ -128,7 +128,7 @@ static void zh_spi_init(void); * * @return Byte received from the slave during the transfer */ -static uint8_t zh_spi_transfer(uint8_t data); +static uint8_t _zh_spi_transfer(uint8_t data); /** * @brief Initialize the nRF24L01+ transceiver for TX-only operation. @@ -137,16 +137,16 @@ static uint8_t zh_spi_transfer(uint8_t data); * settings, channel, RF power and data rate, and loads the gateway address * into both TX and RX pipe 0 registers. */ -static void zh_nrf24_init(void); +static void _zh_nrf24_init(void); /** * @brief Initialize INT0 external interrupt for the nRF24 IRQ signal. * * Configures PD2 as a falling-edge triggered external interrupt source and - * enables the INT0 interrupt mask bit. The ISR sets the nrf_event flag used + * enables the INT0 interrupt mask bit. The ISR sets the _nrf_event flag used * by the pairing state machine. */ -static void zh_nrf24_interrupt_init(void); +static void _zh_nrf24_interrupt_init(void); /** * @brief Transmit a payload buffer through the nRF24L01+ module. @@ -158,7 +158,7 @@ static void zh_nrf24_interrupt_init(void); * @param buf Pointer to the payload data to transmit (must not be NULL) * @param size Number of bytes in the payload buffer (must be > 0) */ -static void zh_nrf24_send(uint8_t *buf, uint8_t size); +static void _zh_nrf24_send(uint8_t *buf, uint8_t size); /** * @brief Start a transmission without blocking on completion. @@ -169,7 +169,7 @@ static void zh_nrf24_send(uint8_t *buf, uint8_t size); * @param buf Pointer to the payload data to transmit (must not be NULL) * @param size Number of bytes in the payload buffer (must be > 0) */ -static void zh_nrf24_send_no_wait(uint8_t *buf, uint8_t size); +static void _zh_nrf24_send_no_wait(uint8_t *buf, uint8_t size); /** * @brief Send a single-byte command to the nRF24L01+ and read the status. @@ -178,7 +178,7 @@ static void zh_nrf24_send_no_wait(uint8_t *buf, uint8_t size); * * @return Status register value returned by the nRF24L01+ */ -static uint8_t zh_nrf24_send_command(uint8_t cmd); +static uint8_t _zh_nrf24_send_command(uint8_t cmd); /** * @brief Write a data buffer to the nRF24L01+ via SPI with a given command. @@ -192,7 +192,7 @@ static uint8_t zh_nrf24_send_command(uint8_t cmd); * * @return Status register value returned by the nRF24L01+ */ -static uint8_t zh_nrf24_write_buffer(uint8_t cmd, uint8_t *buf, uint8_t count); +static uint8_t _zh_nrf24_write_buffer(uint8_t cmd, uint8_t *buf, uint8_t count); /** * @brief Write a single byte value to an nRF24L01+ register. @@ -202,12 +202,12 @@ static uint8_t zh_nrf24_write_buffer(uint8_t cmd, uint8_t *buf, uint8_t count); * * @return Status register value returned by the nRF24L01+ */ -static uint8_t zh_nrf24_write_register(uint8_t reg, uint8_t val); +static uint8_t _zh_nrf24_write_register(uint8_t reg, uint8_t val); /** * @brief Write a multi-byte buffer into an nRF24L01+ register. * - * Convenience wrapper around zh_nrf24_write_buffer that prepends the + * Convenience wrapper around _zh_nrf24_write_buffer that prepends the * W_REGISTER command to the register address. * * @param reg Register address to write to @@ -216,7 +216,7 @@ static uint8_t zh_nrf24_write_register(uint8_t reg, uint8_t val); * * @return Status register value returned by the nRF24L01+ */ -static uint8_t zh_nrf24_write_buff_register(uint8_t reg, uint8_t *buf, uint8_t count); +static uint8_t _zh_nrf24_write_buff_register(uint8_t reg, uint8_t *buf, uint8_t count); /** * @brief Read the received payload from the nRF24L01+ into a buffer. @@ -224,43 +224,43 @@ static uint8_t zh_nrf24_write_buff_register(uint8_t reg, uint8_t *buf, uint8_t c * @param buf Pointer to the destination buffer (must not be NULL) * @param count Number of bytes to read from the RX FIFO */ -static void zh_nrf24_read_payload(uint8_t *buf, uint8_t count); +static void _zh_nrf24_read_payload(uint8_t *buf, uint8_t count); /** * @brief Read the width of the payload in the nRF24L01+ RX FIFO. * * @return Payload width in bytes */ -static uint8_t zh_nrf24_read_payload_width(void); +static uint8_t _zh_nrf24_read_payload_width(void); /** * @brief Switch the nRF24L01+ to RX mode on pipe 0. */ -static void zh_nrf24_enter_rx(void); +static void _zh_nrf24_enter_rx(void); /** * @brief Put the nRF24L01+ into power-down mode. */ -static void zh_nrf24_enter_power_down(void); +static void _zh_nrf24_enter_power_down(void); /** * @brief Start the watchdog timer in interrupt mode with the given timeout. * * @param timeout_bits Watchdog timeout prescaler bits (WDP3:0) */ -static void zh_wdt_start(uint8_t timeout_bits); +static void _zh_wdt_start(uint8_t timeout_bits); /** * @brief Stop the watchdog timer. */ -static void zh_wdt_stop(void); +static void _zh_wdt_stop(void); /** * @brief Generate a pseudo-random token from MCU state and ADC noise. * * @return 16-bit random token (never zero) */ -static uint16_t zh_get_random_token(void); +static uint16_t _zh_get_random_token(void); /** * @brief Run the non-blocking pairing procedure to obtain a device id. @@ -271,7 +271,7 @@ static uint16_t zh_get_random_token(void); * * @return Device identifier assigned by the gateway */ -static uint8_t zh_do_pairing(void); +static uint8_t _zh_do_pairing(void); /** * @brief Enter permanent power-down sleep until the next reset. @@ -279,7 +279,7 @@ static uint8_t zh_do_pairing(void); * Disables all interrupts, the watchdog, the radio, the ADC, SPI and all * unused peripheral clocks, then loops in power-down sleep mode. */ -static void zh_enter_final_sleep(void); +static void _zh_enter_final_sleep(void); /** * @brief Measure the battery voltage using the internal AVcc reference. @@ -290,56 +290,56 @@ static void zh_enter_final_sleep(void); * * @return Battery voltage in volts, or 0.0 if the ADC reading is zero */ -static float zh_get_battery_voltage(void); +static float _zh_get_battery_voltage(void); -static volatile uint8_t send_request = false; -static volatile uint8_t nrf_event = false; +static volatile bool _send_request = false; +static volatile bool _nrf_event = false; -zh_nrf24_sensor_transmitted_data_t transmitted_data = {0}; +zh_nrf24_sensor_transmitted_data_t _transmitted_data = {0}; int main(void) { - transmitted_data.type = ZH_NRF24_SENSOR_TOUCH_SWITCH; + _transmitted_data.type = ZH_NRF24_SENSOR_TOUCH_SWITCH; MCUSR &= ~(1 << WDRF); wdt_disable(); cli(); - zh_pad_interrupt_init(); - zh_spi_init(); - zh_nrf24_init(); + _zh_pad_interrupt_init(); + _zh_spi_init(); + _zh_nrf24_init(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sei(); - uint8_t device_id = zh_load_device_id(); + uint8_t device_id = _zh_load_device_id(); if (device_id == DEVICE_ID_UNASSIGNED) { - device_id = zh_do_pairing(); + device_id = _zh_do_pairing(); } - transmitted_data.id = (int16_t)device_id; + _transmitted_data.id = (int16_t)device_id; { uint8_t probe[ZH_NRF24_MAX_PAYLOAD_SIZE]; - if (zh_nrf24_sensor_build_payload(&transmitted_data, probe, sizeof(probe)) == 0) + if (zh_nrf24_sensor_build_payload(&_transmitted_data, probe, sizeof(probe)) == 0) { - zh_enter_final_sleep(); + _zh_enter_final_sleep(); } } for (;;) { - if (send_request == true) + if (_send_request == true) { cli(); - send_request = false; + _send_request = false; sei(); - transmitted_data.battery = (int16_t)lroundf(zh_get_battery_voltage() * 100.0); + _transmitted_data.battery = (int16_t)lroundf(_zh_get_battery_voltage() * 100.0); uint8_t payload[ZH_NRF24_MAX_PAYLOAD_SIZE]; - uint8_t size = zh_nrf24_sensor_build_payload(&transmitted_data, payload, sizeof(payload)); + uint8_t size = zh_nrf24_sensor_build_payload(&_transmitted_data, payload, sizeof(payload)); if (size > 0) { - zh_nrf24_send(payload, size); + _zh_nrf24_send(payload, size); } } else { cli(); - if (send_request == false) + if (_send_request == false) { sleep_enable(); sei(); @@ -354,19 +354,19 @@ int main(void) ISR(INT1_vect) { - send_request = true; + _send_request = true; } ISR(INT0_vect) { - nrf_event = true; + _nrf_event = true; } ISR(WDT_vect) { } -static uint8_t zh_load_device_id(void) +static uint8_t _zh_load_device_id(void) { uint8_t id = eeprom_read_byte(EEPROM_DEVICE_ID_ADDR); if (id == 0xFF || id == 0x00) @@ -376,12 +376,12 @@ static uint8_t zh_load_device_id(void) return id; } -static void zh_save_device_id(uint8_t id) +static void _zh_save_device_id(uint8_t id) { eeprom_update_byte(EEPROM_DEVICE_ID_ADDR, id); } -static void zh_pad_interrupt_init(void) +static void _zh_pad_interrupt_init(void) { DDRD &= ~(1 << PD3); PORTD &= ~(1 << PD3); @@ -391,14 +391,14 @@ static void zh_pad_interrupt_init(void) EIMSK |= (1 << INT1); } -static void zh_spi_init(void) +static void _zh_spi_init(void) { DDRB |= (1 << PB2) | (1 << PB3) | (1 << PB5); PORTB |= (1 << PB2); SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); } -static uint8_t zh_spi_transfer(uint8_t data) +static uint8_t _zh_spi_transfer(uint8_t data) { SPDR = data; while ((SPSR & (1 << SPIF)) == 0) @@ -407,7 +407,7 @@ static uint8_t zh_spi_transfer(uint8_t data) return SPDR; } -static void zh_nrf24_init(void) +static void _zh_nrf24_init(void) { _delay_ms(100); DDRB |= (1 << PB1); @@ -416,23 +416,23 @@ static void zh_nrf24_init(void) PORTD |= (1 << PD2); uint64_t gateway_address = GATEWAY_ADDRESS; uint8_t activation_key = 0x73; - zh_nrf24_write_register(NRF_REG_CONFIG, 0x00); - zh_nrf24_write_register(NRF_REG_EN_AA, 0x01); - zh_nrf24_write_register(NRF_REG_EN_RXADDR, 0x01); - zh_nrf24_write_register(NRF_REG_SETUP_AW, 0x01); - zh_nrf24_write_register(NRF_REG_SETUP_RETR, 0xFF); - zh_nrf24_write_register(NRF_REG_RF_CH, GATEWAY_CHANNEL); - zh_nrf24_write_register(NRF_REG_RF_SETUP, 0x26); - zh_nrf24_write_buff_register(NRF_REG_TX_ADDR, (uint8_t *)&gateway_address, 3); - zh_nrf24_write_buff_register(NRF_REG_RX_ADDR_P0, (uint8_t *)&gateway_address, 3); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT); - zh_nrf24_write_buffer(NRF_CMD_ACTIVATE, &activation_key, sizeof(activation_key)); - zh_nrf24_write_register(NRF_REG_FEATURE, NRF_FEATURE_EN_DPL); - zh_nrf24_write_register(NRF_REG_DYNPD, NRF_DYNPD_DPL_P0); - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC); + _zh_nrf24_write_register(NRF_REG_CONFIG, 0x00); + _zh_nrf24_write_register(NRF_REG_EN_AA, 0x01); + _zh_nrf24_write_register(NRF_REG_EN_RXADDR, 0x01); + _zh_nrf24_write_register(NRF_REG_SETUP_AW, 0x01); + _zh_nrf24_write_register(NRF_REG_SETUP_RETR, 0xFF); + _zh_nrf24_write_register(NRF_REG_RF_CH, GATEWAY_CHANNEL); + _zh_nrf24_write_register(NRF_REG_RF_SETUP, 0x26); + _zh_nrf24_write_buff_register(NRF_REG_TX_ADDR, (uint8_t *)&gateway_address, 3); + _zh_nrf24_write_buff_register(NRF_REG_RX_ADDR_P0, (uint8_t *)&gateway_address, 3); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT); + _zh_nrf24_write_buffer(NRF_CMD_ACTIVATE, &activation_key, sizeof(activation_key)); + _zh_nrf24_write_register(NRF_REG_FEATURE, NRF_FEATURE_EN_DPL); + _zh_nrf24_write_register(NRF_REG_DYNPD, NRF_DYNPD_DPL_P0); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC); } -static void zh_nrf24_interrupt_init(void) +static void _zh_nrf24_interrupt_init(void) { DDRD &= ~(1 << PD2); PORTD |= (1 << PD2); @@ -442,12 +442,12 @@ static void zh_nrf24_interrupt_init(void) EIMSK |= (1 << INT0); } -static void zh_nrf24_send(uint8_t *buf, uint8_t size) +static void _zh_nrf24_send(uint8_t *buf, uint8_t size) { - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP); _delay_ms(5); - zh_nrf24_send_command(NRF_CMD_FLUSH_TX); - zh_nrf24_write_buffer(NRF_CMD_W_TX_PAYLOAD, buf, size); + _zh_nrf24_send_command(NRF_CMD_FLUSH_TX); + _zh_nrf24_write_buffer(NRF_CMD_W_TX_PAYLOAD, buf, size); PORTB |= (1 << PB1); uint8_t count = 0; while ((PIND & (1 << PD2)) != 0) @@ -459,97 +459,97 @@ static void zh_nrf24_send(uint8_t *buf, uint8_t size) _delay_ms(1); } PORTB &= ~(1 << PB1); - uint8_t status = zh_nrf24_send_command(NRF_CMD_NOP); - zh_nrf24_write_register(NRF_REG_STATUS, status); - zh_nrf24_send_command(NRF_CMD_FLUSH_TX); - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC); + uint8_t status = _zh_nrf24_send_command(NRF_CMD_NOP); + _zh_nrf24_write_register(NRF_REG_STATUS, status); + _zh_nrf24_send_command(NRF_CMD_FLUSH_TX); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC); } -static void zh_nrf24_send_no_wait(uint8_t *buf, uint8_t size) +static void _zh_nrf24_send_no_wait(uint8_t *buf, uint8_t size) { PORTB &= ~(1 << PB1); - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP); _delay_ms(2); - zh_nrf24_send_command(NRF_CMD_FLUSH_TX); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); - zh_nrf24_write_buffer(NRF_CMD_W_TX_PAYLOAD, buf, size); + _zh_nrf24_send_command(NRF_CMD_FLUSH_TX); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); + _zh_nrf24_write_buffer(NRF_CMD_W_TX_PAYLOAD, buf, size); PORTB |= (1 << PB1); _delay_us(15); PORTB &= ~(1 << PB1); } -static uint8_t zh_nrf24_send_command(uint8_t cmd) +static uint8_t _zh_nrf24_send_command(uint8_t cmd) { PORTB &= ~(1 << PB2); - uint8_t status = zh_spi_transfer(cmd); + uint8_t status = _zh_spi_transfer(cmd); PORTB |= (1 << PB2); return status; } -static uint8_t zh_nrf24_write_buffer(uint8_t cmd, uint8_t *buf, uint8_t count) +static uint8_t _zh_nrf24_write_buffer(uint8_t cmd, uint8_t *buf, uint8_t count) { PORTB &= ~(1 << PB2); - uint8_t status = zh_spi_transfer(cmd); + uint8_t status = _zh_spi_transfer(cmd); while (count-- != 0) { - zh_spi_transfer(*(buf++)); + _zh_spi_transfer(*(buf++)); } PORTB |= (1 << PB2); return status; } -static uint8_t zh_nrf24_write_register(uint8_t reg, uint8_t val) +static uint8_t _zh_nrf24_write_register(uint8_t reg, uint8_t val) { PORTB &= ~(1 << PB2); - uint8_t status = zh_spi_transfer(reg | NRF_CMD_W_REGISTER); - zh_spi_transfer(val); + uint8_t status = _zh_spi_transfer(reg | NRF_CMD_W_REGISTER); + _zh_spi_transfer(val); PORTB |= (1 << PB2); return status; } -static uint8_t zh_nrf24_write_buff_register(uint8_t reg, uint8_t *buf, uint8_t count) +static uint8_t _zh_nrf24_write_buff_register(uint8_t reg, uint8_t *buf, uint8_t count) { - return zh_nrf24_write_buffer((reg | NRF_CMD_W_REGISTER), buf, count); + return _zh_nrf24_write_buffer((reg | NRF_CMD_W_REGISTER), buf, count); } -static void zh_nrf24_read_payload(uint8_t *buf, uint8_t count) +static void _zh_nrf24_read_payload(uint8_t *buf, uint8_t count) { PORTB &= ~(1 << PB2); - zh_spi_transfer(NRF_CMD_R_RX_PAYLOAD); + _zh_spi_transfer(NRF_CMD_R_RX_PAYLOAD); while (count-- != 0) { - *buf++ = zh_spi_transfer(0xFF); + *buf++ = _zh_spi_transfer(0xFF); } PORTB |= (1 << PB2); } -static uint8_t zh_nrf24_read_payload_width(void) +static uint8_t _zh_nrf24_read_payload_width(void) { PORTB &= ~(1 << PB2); - zh_spi_transfer(NRF_CMD_R_RX_PL_WID); - uint8_t width = zh_spi_transfer(0xFF); + _zh_spi_transfer(NRF_CMD_R_RX_PL_WID); + uint8_t width = _zh_spi_transfer(0xFF); PORTB |= (1 << PB2); return width; } -static void zh_nrf24_enter_rx(void) +static void _zh_nrf24_enter_rx(void) { PORTB &= ~(1 << PB1); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); - zh_nrf24_send_command(NRF_CMD_FLUSH_RX); - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP | NRF_CONFIG_PRIM_RX); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); + _zh_nrf24_send_command(NRF_CMD_FLUSH_RX); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP | NRF_CONFIG_PRIM_RX); _delay_ms(2); PORTB |= (1 << PB1); _delay_us(130); } -static void zh_nrf24_enter_power_down(void) +static void _zh_nrf24_enter_power_down(void) { PORTB &= ~(1 << PB1); - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_EN_CRC); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_EN_CRC); } -static void zh_wdt_start(uint8_t timeout_bits) +static void _zh_wdt_start(uint8_t timeout_bits) { uint8_t wdp = (timeout_bits & 0x07) | ((timeout_bits & 0x08) ? (1 << WDP3) : 0); cli(); @@ -559,7 +559,7 @@ static void zh_wdt_start(uint8_t timeout_bits) sei(); } -static void zh_wdt_stop(void) +static void _zh_wdt_stop(void) { cli(); wdt_reset(); @@ -568,7 +568,7 @@ static void zh_wdt_stop(void) sei(); } -static uint16_t zh_get_random_token(void) +static uint16_t _zh_get_random_token(void) { uint16_t token = MCUSR; MCUSR = 0; @@ -591,16 +591,16 @@ static uint16_t zh_get_random_token(void) return token; } -static uint8_t zh_do_pairing(void) +static uint8_t _zh_do_pairing(void) { - uint16_t token = zh_get_random_token(); + uint16_t token = _zh_get_random_token(); zh_nrf24_sensor_pairing_data_t pairing_request; - pairing_request.type = (uint8_t)transmitted_data.type; + pairing_request.type = (uint8_t)_transmitted_data.type; pairing_request.magic = ZH_NRF24_PAIRING_REQ_MAGIC; pairing_request.token_hi = (uint8_t)(token >> 8); pairing_request.token_lo = (uint8_t)(token & 0xFF); pairing_request.id = 0; - zh_nrf24_interrupt_init(); + _zh_nrf24_interrupt_init(); zh_nrf24_sensor_pairing_state_t state = ZH_NRF24_PAIR_SEND; uint8_t attempts = 0; for (;;) @@ -608,34 +608,34 @@ static uint8_t zh_do_pairing(void) switch (state) { case ZH_NRF24_PAIR_SEND: - nrf_event = false; - zh_nrf24_send_no_wait((uint8_t *)&pairing_request, ZH_NRF24_PAIRING_PACKET_SIZE); + _nrf_event = false; + _zh_nrf24_send_no_wait((uint8_t *)&pairing_request, ZH_NRF24_PAIRING_PACKET_SIZE); state = ZH_NRF24_PAIR_TX_WAIT; break; case ZH_NRF24_PAIR_TX_WAIT: if ((PIND & (1 << PD2)) == 0) { - nrf_event = true; + _nrf_event = true; } else { - nrf_event = false; - zh_wdt_start(WDT_T_250MS); + _nrf_event = false; + _zh_wdt_start(WDT_T_250MS); sleep_enable(); sei(); sleep_cpu(); sleep_disable(); - zh_wdt_stop(); + _zh_wdt_stop(); sei(); } - if (nrf_event == true) + if (_nrf_event == true) { - nrf_event = false; - uint8_t status = zh_nrf24_send_command(NRF_CMD_NOP); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); + _nrf_event = false; + uint8_t status = _zh_nrf24_send_command(NRF_CMD_NOP); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); if ((status & NRF_STATUS_TX_DS) != 0) { - zh_nrf24_enter_rx(); + _zh_nrf24_enter_rx(); state = ZH_NRF24_PAIR_RX_WAIT; } else @@ -651,53 +651,53 @@ static uint8_t zh_do_pairing(void) case ZH_NRF24_PAIR_RX_WAIT: if ((PIND & (1 << PD2)) == 0) { - nrf_event = true; + _nrf_event = true; } else { - nrf_event = false; - zh_wdt_start(WDT_T_250MS); + _nrf_event = false; + _zh_wdt_start(WDT_T_250MS); sleep_enable(); sei(); sleep_cpu(); sleep_disable(); - zh_wdt_stop(); + _zh_wdt_stop(); sei(); } - if (nrf_event == true) + if (_nrf_event == true) { - nrf_event = false; - uint8_t status = zh_nrf24_send_command(NRF_CMD_NOP); + _nrf_event = false; + uint8_t status = _zh_nrf24_send_command(NRF_CMD_NOP); if ((status & NRF_STATUS_RX_DR) != 0) { - uint8_t width = zh_nrf24_read_payload_width(); + uint8_t width = _zh_nrf24_read_payload_width(); if (width > ZH_NRF24_MAX_PAYLOAD_SIZE) { - zh_nrf24_send_command(NRF_CMD_FLUSH_RX); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR); + _zh_nrf24_send_command(NRF_CMD_FLUSH_RX); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR); state = ZH_NRF24_PAIR_BACKOFF; break; } if (width != ZH_NRF24_PAIRING_PACKET_SIZE) { uint8_t dummy[ZH_NRF24_MAX_PAYLOAD_SIZE]; - zh_nrf24_read_payload(dummy, width); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR); - zh_nrf24_send_command(NRF_CMD_FLUSH_RX); + _zh_nrf24_read_payload(dummy, width); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR); + _zh_nrf24_send_command(NRF_CMD_FLUSH_RX); state = ZH_NRF24_PAIR_BACKOFF; break; } zh_nrf24_sensor_pairing_data_t pairing_response; - zh_nrf24_read_payload((uint8_t *)&pairing_response, width); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT); - zh_nrf24_send_command(NRF_CMD_FLUSH_RX); + _zh_nrf24_read_payload((uint8_t *)&pairing_response, width); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT); + _zh_nrf24_send_command(NRF_CMD_FLUSH_RX); if (pairing_response.magic == ZH_NRF24_PAIRING_ACK_MAGIC && pairing_response.type == pairing_request.type && pairing_response.token_hi == pairing_request.token_hi && pairing_response.token_lo == pairing_request.token_lo && pairing_response.id != 0 && pairing_response.id != DEVICE_ID_UNASSIGNED) { - zh_nrf24_enter_power_down(); + _zh_nrf24_enter_power_down(); EIMSK &= ~(1 << INT0); - zh_save_device_id(pairing_response.id); + _zh_save_device_id(pairing_response.id); return pairing_response.id; } } @@ -709,18 +709,18 @@ static uint8_t zh_do_pairing(void) } break; case ZH_NRF24_PAIR_BACKOFF: - zh_nrf24_enter_power_down(); - nrf_event = false; - zh_wdt_start(WDT_T_4S); + _zh_nrf24_enter_power_down(); + _nrf_event = false; + _zh_wdt_start(WDT_T_4S); sleep_enable(); sei(); sleep_cpu(); sleep_disable(); - zh_wdt_stop(); + _zh_wdt_stop(); sei(); if (++attempts >= PAIRING_TIMEOUT_ATTEMPTS) { - zh_enter_final_sleep(); + _zh_enter_final_sleep(); } state = ZH_NRF24_PAIR_SEND; break; @@ -728,14 +728,14 @@ static uint8_t zh_do_pairing(void) } } -static void zh_enter_final_sleep(void) +static void _zh_enter_final_sleep(void) { cli(); EIMSK = 0; EIFR = 0xFF; - zh_wdt_stop(); + _zh_wdt_stop(); PORTB &= ~(1 << PB1); - zh_nrf24_write_register(NRF_REG_CONFIG, 0x00); + _zh_nrf24_write_register(NRF_REG_CONFIG, 0x00); ADCSRA = 0; SPCR = 0; PRR = (1 << PRTWI) | (1 << PRTIM2) | (1 << PRTIM1) | (1 << PRTIM0) | (1 << PRSPI) | (1 << PRUSART0); @@ -747,7 +747,7 @@ static void zh_enter_final_sleep(void) } } -static float zh_get_battery_voltage(void) +static float _zh_get_battery_voltage(void) { ADMUX = (1 << REFS0) | (1 << MUX3) | (1 << MUX2) | (1 << MUX1); ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); diff --git a/wiki_ru.md b/wiki_ru.md index 0d70e71..064668f 100644 --- a/wiki_ru.md +++ b/wiki_ru.md @@ -25,7 +25,7 @@ Прошивка не использует динамическое выделение памяти. Все данные хранятся в статической области и регистрах микроконтроллера. -Пакет формируется в глобальной переменной `transmitted_data` типа `zh_nrf24_sensor_transmitted_data_t` из внешней библиотеки `zh_nrf24_config` и сериализуется функцией `zh_nrf24_sensor_build_payload()` перед передачей. +Пакет формируется в глобальной переменной `_transmitted_data` типа `zh_nrf24_sensor_transmitted_data_t` из внешней библиотеки `zh_nrf24_config` и сериализуется функцией `zh_nrf24_sensor_build_payload()` перед передачей. | Поле | Тип | Описание | | ------ | ----- | ---------- | @@ -47,83 +47,83 @@ ### Управление памятью -Прошивка не использует динамическую память. Глобальная переменная `transmitted_data` заполняется при старте (идентификатор и тип), в рабочем цикле обновляется только поле `battery`. Флаги `send_request`, `nrf_event` объявлены как `static volatile uint8_t` для корректного доступа из ISR и главного цикла. +Прошивка не использует динамическую память. Глобальная переменная `_transmitted_data` заполняется при старте (идентификатор и тип), в рабочем цикле обновляется только поле `battery`. Флаги `_send_request`, `_nrf_event` объявлены как `static volatile bool` для корректного доступа из ISR и главного цикла. ### Флаги синхронизации | Флаг | Устанавливается | Используется | | ------ | ----------------- | -------------- | -| `send_request` | ISR `INT1_vect` (касание) | Главный цикл — запуск передачи | -| `nrf_event` | ISR `INT0_vect` (IRQ nRF24) | Конечный автомат сопряжения | +| `_send_request` | ISR `INT1_vect` (касание) | Главный цикл — запуск передачи | +| `_nrf_event` | ISR `INT0_vect` (IRQ nRF24) | Конечный автомат сопряжения | --- ## API (интерфейс) -Все функции являются `static` и доступны только внутри модуля `main.c`. +Все функции являются `static` и доступны только внутри модуля `src/zh_avr_touch_pad.c`. Имена функций имеют префикс `_zh_`. ### Инициализация | Функция | Описание | | --------- | ---------- | -| `zh_pad_interrupt_init()` | Настройка внешнего прерывания INT1 (PD3, rising edge) для пробуждения по касанию | -| `zh_spi_init()` | Инициализация аппаратного SPI в режиме мастера (Fosc/16) | -| `zh_nrf24_init()` | Инициализация трансивера nRF24L01+ в режим передачи | -| `zh_nrf24_interrupt_init()` | Настройка внешнего прерывания INT0 (PD2, falling edge) для сигнала IRQ nRF24 | +| `_zh_pad_interrupt_init()` | Настройка внешнего прерывания INT1 (PD3, rising edge) для пробуждения по касанию | +| `_zh_spi_init()` | Инициализация аппаратного SPI в режиме мастера (Fosc/16) | +| `_zh_nrf24_init()` | Инициализация трансивера nRF24L01+ в режим передачи | +| `_zh_nrf24_interrupt_init()` | Настройка внешнего прерывания INT0 (PD2, falling edge) для сигнала IRQ nRF24 | ### Работа с EEPROM | Функция | Описание | |---------|----------| -| `zh_load_device_id()` | Чтение идентификатора устройства из EEPROM, возврат `DEVICE_ID_UNASSIGNED` если не сохранён | -| `zh_save_device_id()` | Сохранение идентификатора устройства в EEPROM | +| `_zh_load_device_id()` | Чтение идентификатора устройства из EEPROM, возврат `DEVICE_ID_UNASSIGNED` если не сохранён | +| `_zh_save_device_id()` | Сохранение идентификатора устройства в EEPROM | ### Измерение | Функция | Описание | |---------|----------| -| `zh_get_battery_voltage()` | Измерение напряжения батареи через внутренний АЦП с опорой 1,1 В, возврат значения в вольтах | -| `zh_get_random_token()` | Генерация 16-битного псевдослучайного токена из шума АЦП и MCUSR для запроса сопряжения | +| `_zh_get_battery_voltage()` | Измерение напряжения батареи через внутренний АЦП с опорой 1,1 В, возврат значения в вольтах | +| `_zh_get_random_token()` | Генерация 16-битного псевдослучайного токена из шума АЦП и MCUSR для запроса сопряжения | ### Передача данных | Функция | Описание | |---------|----------| -| `zh_nrf24_send()` | Блокирующая передача буфера через nRF24L01+ с ожиданием завершения по пину IRQ (таймаут 100 мс) | -| `zh_nrf24_send_no_wait()` | Неблокирующая передача — загружает буфер, импульс CE 15 мкс, завершение по прерыванию IRQ | +| `_zh_nrf24_send()` | Блокирующая передача буфера через nRF24L01+ с ожиданием завершения по пину IRQ (таймаут 100 мс) | +| `_zh_nrf24_send_no_wait()` | Неблокирующая передача — загружает буфер, импульс CE 15 мкс, завершение по прерыванию IRQ | ### Управление режимами nRF24L01+ | Функция | Описание | |---------|----------| -| `zh_nrf24_enter_rx()` | Переключение nRF24L01+ в режим приёма на трубе 0 | -| `zh_nrf24_enter_power_down()` | Перевод nRF24L01+ в режим Power Down | +| `_zh_nrf24_enter_rx()` | Переключение nRF24L01+ в режим приёма на трубе 0 | +| `_zh_nrf24_enter_power_down()` | Перевод nRF24L01+ в режим Power Down | ### Низкоуровневые SPI-операции | Функция | Описание | | --------- | ---------- | -| `zh_spi_transfer()` | Обмен одного байта по SPI (полный дуплекс) | -| `zh_nrf24_send_command()` | Отправка однобайтовой команды и чтение регистра статуса | -| `zh_nrf24_write_register()` | Запись одного байта в регистр nRF24L01+ | -| `zh_nrf24_write_buff_register()` | Запись многобайтового буфера в регистр nRF24L01+ | -| `zh_nrf24_write_buffer()` | Запись буфера данных с указанной SPI-командой | -| `zh_nrf24_read_payload()` | Чтение принятого пакета из RX FIFO nRF24 в буфер | -| `zh_nrf24_read_payload_width()` | Чтение длины пакета в RX FIFO nRF24 | +| `_zh_spi_transfer()` | Обмен одного байта по SPI (полный дуплекс) | +| `_zh_nrf24_send_command()` | Отправка однобайтовой команды и чтение регистра статуса | +| `_zh_nrf24_write_register()` | Запись одного байта в регистр nRF24L01+ | +| `_zh_nrf24_write_buff_register()` | Запись многобайтового буфера в регистр nRF24L01+ | +| `_zh_nrf24_write_buffer()` | Запись буфера данных с указанной SPI-командой | +| `_zh_nrf24_read_payload()` | Чтение принятого пакета из RX FIFO nRF24 в буфер | +| `_zh_nrf24_read_payload_width()` | Чтение длины пакета в RX FIFO nRF24 | ### Watchdog-таймер | Функция | Описание | |---------|----------| -| `zh_wdt_start()` | Запуск watchdog-таймера в режиме прерывания с указанным таймаутом | -| `zh_wdt_stop()` | Остановка watchdog-таймера | +| `_zh_wdt_start()` | Запуск watchdog-таймера в режиме прерывания с указанным таймаутом | +| `_zh_wdt_stop()` | Остановка watchdog-таймера | ### Сон и сопряжение | Функция | Описание | |---------|----------| -| `zh_do_pairing()` | Запуск конечного автомата сопряжения со шлюзом для получения идентификатора | -| `zh_enter_final_sleep()` | Переход в окончательный Power-down сон до сброса: отключение всех прерываний, watchdog, радиомодуля, АЦП, SPI и неиспользуемых периферийных блоков | +| `_zh_do_pairing()` | Запуск конечного автомата сопряжения со шлюзом для получения идентификатора | +| `_zh_enter_final_sleep()` | Переход в окончательный Power-down сон до сброса: отключение всех прерываний, watchdog, радиомодуля, АЦП, SPI и неиспользуемых периферийных блоков | --- @@ -131,9 +131,9 @@ Прошивка работает на bare-metal AVR без RTOS. Синхронизация между прерываниями и главным циклом реализуется следующим образом: -1. **Флаги `volatile`** — переменные `send_request`, `nrf_event` объявлены как `static volatile uint8_t`, что гарантирует чтение актуального значения из памяти при каждой проверке в главном цикле. +1. **Флаги `volatile`** — переменные `_send_request`, `_nrf_event` объявлены как `static volatile bool`, что гарантирует чтение актуального значения из памяти при каждой проверке в главном цикле. 2. **Атомарная запись из ISR** — обработка прерывания устанавливает флаг в `true`. Запись одного байта на AVR является атомарной операцией. -3. **Отключение прерываний при проверке и сбросе флага** — `cli()` перед проверкой и сбросом `send_request` в главном цикле исключает гонку между ISR и главным циклом. +3. **Отключение прерываний при проверке и сбросе флага** — `cli()` перед проверкой и сбросом `_send_request` в главном цикле исключает гонку между ISR и главным циклом. 4. **Отключение прерываний при инициализации** — `cli()` перед настройкой периферии исключает гонки при старте. --- @@ -142,12 +142,12 @@ ### Алгоритм сопряжения (pairing) -Конечный автомат `zh_do_pairing()` работает в четырёх состояниях: +Конечный автомат `_zh_do_pairing()` работает в четырёх состояниях: -1. **`ZH_NRF24_PAIR_SEND`** — генерируется псевдослучайный токен, формируется пакет запроса (`zh_nrf24_sensor_pairing_data_t` с `magic = ZH_NRF24_PAIRING_REQ_MAGIC`), выполняется неблокирующая передача через `zh_nrf24_send_no_wait()`. +1. **`ZH_NRF24_PAIR_SEND`** — генерируется псевдослучайный токен, формируется пакет запроса (`zh_nrf24_sensor_pairing_data_t` с `magic = ZH_NRF24_PAIRING_REQ_MAGIC`), выполняется неблокирующая передача через `_zh_nrf24_send_no_wait()`. 2. **`ZH_NRF24_PAIR_TX_WAIT`** — ожидание прерывания IRQ (завершение передачи). Если пин IRQ уже низкий — событие считается наступившим. Иначе — переход в сон с watchdog-таймером 250 мс. При флаге `TX_DS` — переход в приём, при `MAX_RT` — в backoff. 3. **`ZH_NRF24_PAIR_RX_WAIT`** — ожидание ответа шлюза. При получении пакета проверяется: длина равна `ZH_NRF24_PAIRING_PACKET_SIZE`, `magic == ZH_NRF24_PAIRING_ACK_MAGIC`, тип совпадает, токен совпадает, `id != 0` и `id != DEVICE_ID_UNASSIGNED`. При успехе — сохранение `id` в EEPROM и возврат. -4. **`ZH_NRF24_PAIR_BACKOFF`** — переход в Power Down, ожидание 4 с через watchdog. После `PAIRING_TIMEOUT_ATTEMPTS` (7) неудачных попыток — переход в `zh_enter_final_sleep()`. +4. **`ZH_NRF24_PAIR_BACKOFF`** — переход в Power Down, ожидание 4 с через watchdog. После `PAIRING_TIMEOUT_ATTEMPTS` (7) неудачных попыток — переход в `_zh_enter_final_sleep()`. ### Алгоритм измерения напряжения батареи @@ -177,10 +177,10 @@ ### Алгоритм сна и пробуждения -- Главный цикл проверяет флаг `send_request`. +- Главный цикл проверяет флаг `_send_request`. - Если флаг не установлен — вызывается `sleep_cpu()` (режим Power-down). - Пробуждение происходит по аппаратному прерыванию INT1 (rising edge на PD3). -- ISR устанавливает `send_request = true`, цикл просыпается и выполняет передачу. +- ISR устанавливает `_send_request = true`, цикл просыпается и выполняет передачу. --- @@ -197,51 +197,51 @@ #include "stdbool.h" #include "zh_nrf24_config.h" -static volatile uint8_t send_request = false; -zh_nrf24_sensor_transmitted_data_t transmitted_data = {0}; +static volatile bool _send_request = false; +zh_nrf24_sensor_transmitted_data_t _transmitted_data = {0}; ISR(INT1_vect) { - send_request = true; + _send_request = true; } int main(void) { - transmitted_data.type = ZH_NRF24_SENSOR_TOUCH_SWITCH; + _transmitted_data.type = ZH_NRF24_SENSOR_TOUCH_SWITCH; MCUSR &= ~(1 << WDRF); wdt_disable(); cli(); - zh_pad_interrupt_init(); - zh_spi_init(); - zh_nrf24_init(); + _zh_pad_interrupt_init(); + _zh_spi_init(); + _zh_nrf24_init(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sei(); // Загрузка или получение идентификатора устройства - uint8_t device_id = zh_load_device_id(); + uint8_t device_id = _zh_load_device_id(); if (device_id == DEVICE_ID_UNASSIGNED) { - device_id = zh_do_pairing(); + device_id = _zh_do_pairing(); } - transmitted_data.id = (int16_t)device_id; + _transmitted_data.id = (int16_t)device_id; for (;;) { - if (send_request == true) + if (_send_request == true) { cli(); - send_request = false; + _send_request = false; sei(); - transmitted_data.battery = (int16_t)lroundf(zh_get_battery_voltage() * 100.0); + _transmitted_data.battery = (int16_t)lroundf(_zh_get_battery_voltage() * 100.0); uint8_t payload[ZH_NRF24_MAX_PAYLOAD_SIZE]; - uint8_t size = zh_nrf24_sensor_build_payload(&transmitted_data, payload, sizeof(payload)); + uint8_t size = zh_nrf24_sensor_build_payload(&_transmitted_data, payload, sizeof(payload)); if (size > 0) { - zh_nrf24_send(payload, size); + _zh_nrf24_send(payload, size); } } else { cli(); - if (send_request == false) + if (_send_request == false) { sleep_enable(); sei(); @@ -284,11 +284,11 @@ int main(void) | Условие | Поведение | | --------- | ----------- | -| Нулевое показание АЦП | `zh_get_battery_voltage()` возвращает `0.0` | +| Нулевое показание АЦП | `_zh_get_battery_voltage()` возвращает `0.0` | | Превышение таймаута передачи (100 мс) | Передача прерывается, пакет теряется | | Неверная длина принятого пакета при сопряжении | Пакет отбрасывается, переход в `ZH_NRF24_PAIR_BACKOFF` | -| Превышение числа попыток сопряжения (7) | `zh_enter_final_sleep()` — сон до сброса | -| `zh_nrf24_sensor_build_payload()` возвращает 0 | Передача пропускается, переход в `zh_enter_final_sleep()` | +| Превышение числа попыток сопряжения (7) | `_zh_enter_final_sleep()` — сон до сброса | +| `zh_nrf24_sensor_build_payload()` возвращает 0 | Передача пропускается, переход в `_zh_enter_final_sleep()` | --- @@ -298,9 +298,9 @@ int main(void) 2. **Отсутствие шифрования** — CRC включён, но AES-шифрование не используется. Пакеты могут быть перехвачены. 3. **Жёстко зашитый адрес и канал шлюза** — смена `GATEWAY_ADDRESS` или `GATEWAY_CHANNEL` требует перепрошивки. 4. **Таймаут блокирующей передачи 100 мс** — если шлюз недоступен, пакет теряется без повторной попытки на уровне приложения (аппаратные ретрансмиты настроены через `SETUP_RETR = 0xFF`: 15 попыток с максимальным интервалом). -5. **Одно сенсорное событие за цикл** — несколько касаний во время передачи будут потеряны (флаг `send_request` — один бит). +5. **Одно сенсорное событие за цикл** — несколько касаний во время передачи будут потеряны (флаг `_send_request` — один бит). 6. **Точность измерения батареи** — зависит от стабильности внутреннего опорного напряжения 1,1 В и может отличаться от реального напряжения на ±3%. -7. **SPI остаётся включённым в режиме сна** — перед окончательным сном SPI отключается в `zh_enter_final_sleep()`, но в штатном режиме ожидания SPI не отключается между передачами. +7. **SPI остаётся включённым в режиме сна** — перед окончательным сном SPI отключается в `_zh_enter_final_sleep()`, но в штатном режиме ожидания SPI не отключается между передачами. --- @@ -326,7 +326,7 @@ pio run -e ATmega328P -t upload ### Подключение в проекте -Компонент является самодостаточной прошивкой — не подключается как библиотека. Для интеграции в другой проект скопируйте `src/main.c`, добавьте зависимость `zh_nrf24_config` и адаптируйте макросы конфигурации. +Компонент является самодостаточной прошивкой — не подключается как библиотека. Для интеграции в другой проект скопируйте `src/zh_avr_touch_pad.c`, добавьте зависимость `zh_nrf24_config` и адаптируйте макросы конфигурации. ```ini ; platformio.ini