#include #include #include #include #include #include #include #include #include #include "led.h" #include "spi.h" #include "nrf24l01.h" #include "nrf24l01_definitions.h" #include "bme280_interface.h" #include "bme280_defs.h" #include "pin_programming.h" #include "crc.h" #include "encryption.h" uint8_t ownId; const uint8_t encryptionKey[16] = {0x9e, 0x37, 0x79, 0xb9, 0x9b, 0x97, 0x73, 0xe9, 0xb9, 0x79, 0x37, 0x9e, 0x6b, 0x69, 0x51, 0x56}; /* TODO: use exernal file with the keys */ uint64_t salt; char bool_case = 0; int timer = 0; int timer_max = 0; volatile uint8_t cycle = 0; volatile bool nrfInterruptRaised; volatile uint8_t interruptCounter; volatile uint8_t executionFlag; static uint8_t messageBuffer[PACKET_LENGTH]; static PACKET * packet = (PACKET*) messageBuffer; void Enter_Power_Save_Mode(void); void Exit_Power_Save_Mode(void); bool Send_Get_Salt_Message(PACKET * packet, uint64_t salt); //TODO: put into own file bool Read_Salt_Message(PACKET * packet, uint64_t * salt); void Set_Up_Power_Save_Mode(void); void Enter_Power_Save_Mode(void); ISR(TIMER2_COMPA_vect) { /* Do nothing as the interrupt is only used to wake up the MCU. */ } ISR(PCINT2_vect) { nrfInterruptRaised = true; } int main (void) { struct bme280_data sensorData; uint16_t crc; bool saltReceived = false; /* Enable the debug LED */ LED_DDR |= (1 << LED_PIN); /* Get the own ID */ Configure_Pin_Programming_Pins(); ownId = Get_Own_Identifier(); /* Initialize the SPI */ Initialize_SPI(); /* Initialize the nrf24l01 */ Initialize_NRF24L01(); // The NRF24L01 is now in the mode Standby-I. /* Configure the transmission parameters (Enhanced ShockBurst)*/ Configure_Transmission(ownId); /* Initialize the BME280 */ Initialize_BME280(); Set_Up_Power_Save_Mode(); /* Initialize the salt */ salt = 0x0ull; salt |= ownId; /* TODO: Request a salt from the base station: * - loop as long as no reply from the base station was received: * - send the packet that requests the salt * - if no ack is received for the packet go direclty to sleep for 100 ms * - if no salt is received within 100 ms send the message again * - keep the LED on for the duration to allow the user to see that the device is ready for operation. */ LED_PORT |= (1 << LED_PIN); do { if (Send_Get_Salt_Message(packet, salt) == true) { memset(messageBuffer, 0x0F, 32); if (NRF24L01_Receive_Message(messageBuffer, 100 /*ms*/) == true) { _delay_ms(10); saltReceived = Read_Salt_Message(packet, &salt); } } else { /* TODO: enter power save mode instead to make the battery life longer */ _delay_ms(100); } } while (saltReceived == false); LED_PORT &= ~(1 << LED_PIN); salt &= 0xFFFFFFFFFFFFFF00ull; salt |= ownId; /* Delay the change of the operating frequency by the function Enter_Power_Save_Mode for the * first function pass. If it is changed before the ISP can flash the MCU the clocks of the ISP * and MCU are mismatched and the flashing will fail. */ _delay_ms(500); while(1) { Enter_Power_Save_Mode(); // The MCU enters the Power Save Mode here. Exit_Power_Save_Mode(); // The MCU exits the Power Save Mode here. if (cycle == 0) // TODO cycle == 7 to execute this every 60 s { /* Re-Initialize the peripherals */ Set_BME280_Pins(); Set_NRF24L01_Pins(); /* Get measurement and send it */ BME280_Get_Measurement(&sensorData); /* TODO: put the following into a Send_Report function */ memset((uint8_t*)packet, 0, PACKET_LENGTH); //Reinitialize the buffer with zeros salt &= ~(1ull<<63); packet->salt = salt; packet->payload.reportData.packetIdentifier.elementCount = 3; packet->payload.reportData.packetIdentifier.packetType = PACKET_TYPE_REPORT; /* Fill in the payload */ packet->payload.reportData.valueTypeTemperature = VALUE_TYPE_TEMPERATURE; packet->payload.reportData.temperature = sensorData.temperature/10; packet->payload.reportData.valueTypePressure = VALUE_TYPE_PRESSURE; packet->payload.reportData.pressure = sensorData.pressure; packet->payload.reportData.valueTypeHumidity = VALUE_TYPE_HUMIDITY; packet->payload.reportData.humidity = sensorData.humidity * 100/1024; /* Calculate the CRC */ crc = Calculate_Crc(packet->payload.buffer, PACKET_PAYLOAD_BUFFER_LENGTH); packet->crc = crc; /* Encrypt the packet */ /* TODO: * - increment the salt for every packet * - Receive salt from the base station */ Encrypt((uint32_t*) packet->payload.buffer, PACKET_PAYLOAD_BUFFER_LENGTH + sizeof(crc), salt, (uint32_t*) encryptionKey); NRF24L01_Send_Message((uint8_t*)packet, PACKET_LENGTH); /* Increment salt */ salt += (1 << 8); LED_PORT |= (1 << LED_PIN); _delay_ms(100); /* TODO: only for debugging, remove this later! */ LED_PORT &= ~(1 << LED_PIN); cycle = 0; } else { cycle ++; } } } void Set_Up_Power_Save_Mode(void) { // Disable Brown-Out-Detection by setting the BODLEVEL 2:0 Fuses to 0b111 (should be default) // Disable the on-chip debug system by setting the DWEN Fuse to 1 (should be default) /* Disable some unused peripherals that are not used during operation of the weather station: */ // The ADC is turned off by default ACSR &= ~(1<salt = salt; packet->payload.reportData.packetIdentifier.elementCount = 0; packet->payload.reportData.packetIdentifier.packetType = PACKET_TYPE_GET_SALT; /* Calculate the CRC */ crc = Calculate_Crc(packet->payload.buffer, PACKET_PAYLOAD_BUFFER_LENGTH); packet->crc = crc; Encrypt((uint32_t*) packet->payload.buffer, PACKET_PAYLOAD_BUFFER_LENGTH + sizeof(crc), salt, (uint32_t*) encryptionKey); success = NRF24L01_Send_Message((uint8_t*)packet, PACKET_LENGTH); return success; } bool Read_Salt_Message(PACKET * packet, uint64_t * salt) { uint16_t crcRemainder = 0xFFFF; uint64_t baseStationSalt = 0x0; /* TODO: check that the packet originated from the base station by checking the id */ baseStationSalt = packet->salt; Decrypt((uint32_t*)packet->payload.buffer, PACKET_PAYLOAD_BUFFER_LENGTH + sizeof(packet->crc), baseStationSalt, (uint32_t*) encryptionKey); crcRemainder = Calculate_Crc(packet->payload.buffer, PACKET_PAYLOAD_BUFFER_LENGTH + sizeof(packet->crc)); if (crcRemainder != 0) { return false; } if ((packet->payload.saltData.packetIdentifier.packetType != PACKET_TYPE_SALT) || (packet->payload.saltData.packetIdentifier.elementCount != 0)) { return false; } memcpy((uint8_t*)salt, packet->payload.saltData.salt, 7); *salt = (*salt) << 8; return true; }