/*** * * void tick() * checks if there is a complete transmission and calls the users callback function * ***/ void megaRF::tick() { rfm12_tick(); uint8_t i=0; if(rfm12_rx_status()==STATUS_COMPLETE){ extbuffer = rfm12_rx_buffer(); for(i=0;i<rfm12_rx_len();i++) { intbuffer[i] = *extbuffer; extbuffer++; } intbuffer[i]='\0'; packetLength=i; rfm12_rx_clear(); // don't bother if user hasn't registered a callback if(!user_onReceive){ } else{ user_onReceive(); } } rfm12_tick(); return; }
// Freigeben des Empfangspuffers für neue Daten void rfm12_receive_clear() { rfm12_receive_buffer.address = 0; rfm12_receive_buffer.len = 0; rfm12_receive_state = receive_idle; rfm12_rx_clear(); // unterlagerten Puffer wieder freigeben }
int main(void) { timeCount = 0; hardwareInit(); uart0_init(BAUD_SETTING); /* Initialise timer to divide by 1025, giving 32ms time tick */ timer0Init(0,5); rfm12_init(); wdtInit(); sei(); indx = 0; for(;;) { wdt_reset(); uint8_t sendMessage = false; uint16_t character = uart0_getc(); /* Wait for a serial incoming message to be built. */ if (character != UART_NO_DATA) { inBuf[indx++] = (uint8_t)(character & 0xFF); /* Signal to transmit if a CR was received, or string too long. */ sendMessage = ((indx > MAX_MESSAGE) || (character == 0x0D)); } /* Send a transmission if message is ready to send, or something was received and time waited is too long. */ if (sendMessage || (timeCount++ > TIMEOUT)) { /* Wait for the transmit buffer to be freed and message loaded. */ if ((indx > 0) && (rfm12_tx(indx, 0, inBuf) != RFM12_TX_OCCUPIED)) indx = 0; timeCount = 0; } rfm12_tick(); /* If an RF incoming message has been received, take it from the buffer one character at a time and transmit via the serial port. */ if (rfm12_rx_status() == STATUS_COMPLETE) { uint8_t *bufferContents = rfm12_rx_buffer(); uint8_t messageLength = rfm12_rx_len(); uint8_t i; for (i=0;i<messageLength;i++) { uart0_putc(bufferContents[i]); } /* Clear the "in use" status of the receive buffer to be available for rfm12lib. */ rfm12_rx_clear(); } } }
int ReceiveFrame(char *Rframe = 0) { int retval; uint8_t *bufptr; if(rfm12_rx_status() == STATUS_COMPLETE){ put_string("\r\nPhysical layer data detected\r\n"); if(Rframe != 0) { bufptr = rfm12_rx_buffer(); for(int k = 0; k < (rfm12_rx_len()); k++) { Rframe[k] = bufptr[k]; } Rframe[rfm12_rx_len()] = '\0'; rfm12_rx_clear(); put_string("\r\nPhysical layer received data: "); put_string(Rframe); } retval = 1; } else { retval = 0; } return retval; }
bufferStruct checkReceiveData(bufferStruct buffer){ rfm12_tick(); //periodic tick function - call that one once in a while switch(state){ case STATE_TIMEOUT: #if STATE_UART_DEBUG >= 2 uart_putstr ("tiOu\r\n"); #endif ++timoutCounter; if(timoutCounter > 5){ #if STATE_UART_DEBUG >= 2 uart_putstr ("tiOuOverl\r\n"); #endif state = STATE_FREE; stopTimer(); timoutCounter = 0; } else { processNack(); } break; case STATE_SENDING_ACK: if(rfm12_tx_status() == STATUS_FREE){ state = STATE_SENDING_DATA; #if STATE_UART_DEBUG >= 2 uart_putstr ("finSeAck\r\n"); #endif bufferStruct result; result.bufferLength = getPayloadLength(backupData.bufferLength, backupData.buffer); memcpy(result.buffer, getPayload(backupData.bufferLength, backupData.buffer), result.bufferLength); uart_putc('%'); uart_putc(result.bufferLength); uart_putc('%'); for(uint8_t i = 0; i < result.bufferLength; ++i){ uart_putc(result.buffer[i]); } uart_putc('%'); return result; } case STATE_SENDING_DATA: if(rfm12_tx_status() == STATUS_FREE){ #if STATE_UART_DEBUG >= 2 uart_putstr ("finSeData\r\n"); #endif state = STATE_FREE; } } //uart_putstr (rfm12_rx_status()); if (rfm12_rx_status() == STATUS_COMPLETE){ bufferStruct tempBuffer; tempBuffer.bufferLength = rfm12_rx_len(); memcpy(tempBuffer.buffer, rfm12_rx_buffer(), tempBuffer.bufferLength); if(validateCrc(tempBuffer)){ #if STATE_UART_DEBUG >= 2 uart_putstr ("crcAck\r\n"); #endif } else { #if STATE_UART_DEBUG >= 2 uart_putstr ("crcNack\r\n"); #endif rfm12_rx_clear(); sendNack(tempBuffer); return buffer; } if(state > STATE_FREE){ if(getAck(tempBuffer.bufferLength, tempBuffer.buffer) & ACK){ #if STATE_UART_DEBUG >= 2 uart_putstr ("rxAck\r\n"); #endif processAck(); } else if(getType(tempBuffer.bufferLength, tempBuffer.buffer) & NACK){ #if STATE_UART_DEBUG >= 2 uart_putstr ("rxNack\r\n"); #endif processNack(); } } if(state == STATE_FREE){ switch(getType(tempBuffer.bufferLength, tempBuffer.buffer)){ case SEND_DATA: #if STATE_UART_DEBUG >= 2 uart_putstr ("send\r\n"); #endif buffer = receiveSendData(tempBuffer); break; // here we should implement the cases of repeating data therefore we would have to know all last data sent // here we should implement the get back to in -> timeframe not yet implemented } } // tell the implementation that the buffer // can be reused for the next data. rfm12_rx_clear(); } return buffer; }
void initCommunication(){ rfm12_init(); // initialize the library sei(); rfm12_rx_clear(); }
int main(void) { uint8_t aes_key_nr; uint8_t loop = 0; uint8_t loop2 = 0; // delay 1s to avoid further communication with uart or RFM12 when my programmer resets the MC after 500ms... _delay_ms(1000); util_init(); check_eeprom_compatibility(DEVICETYPE_BASESTATION); request_queue_init(); // read packetcounter, increase by cycle and write back packetcounter = e2p_generic_get_packetcounter() + PACKET_COUNTER_WRITE_CYCLE; e2p_generic_set_packetcounter(packetcounter); // read device specific config aes_key_count = e2p_basestation_get_aeskeycount(); device_id = e2p_generic_get_deviceid(); uart_init(); UART_PUTS("\r\n"); UART_PUTF4("smarthomatic Base Station v%u.%u.%u (%08lx)\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_HASH); UART_PUTS("(c) 2012..2014 Uwe Freese, www.smarthomatic.org\r\n"); UART_PUTF("Device ID: %u\r\n", device_id); UART_PUTF("Packet counter: %lu\r\n", packetcounter); UART_PUTF("AES key count: %u\r\n", aes_key_count); UART_PUTS("Waiting for incoming data. Press h for help.\r\n\r\n"); led_blink(500, 500, 3); rfm12_init(); sei(); // ENCODE TEST (Move to unit test some day...) /* uint8_t testlen = 32; uint8_t aes_key_num = 0; memset(&bufx[0], 0, sizeof(bufx)); bufx[0] = 0xff; bufx[1] = 0xb0; bufx[2] = 0xa0; bufx[3] = 0x3f; bufx[4] = 0x01; bufx[5] = 0x70; bufx[6] = 0x00; bufx[7] = 0x0c; bufx[8] = 0xa8; bufx[9] = 0x00; bufx[10] = 0x20; bufx[20] = 0x20; eeprom_read_block (aes_key, (uint8_t *)(EEPROM_AESKEYS_BYTE + aes_key_num * 32), 32); UART_PUTS("Using AES key "); print_bytearray((uint8_t *)aes_key, 32); UART_PUTS("Before encryption: "); print_bytearray(bufx, testlen); uint8_t aes_byte_count = aes256_encrypt_cbc(bufx, testlen); UART_PUTF("byte count = %u\r\n", aes_byte_count); UART_PUTS("After encryption: "); print_bytearray(bufx, aes_byte_count); aes256_decrypt_cbc(bufx, aes_byte_count); UART_PUTS("After decryption: "); print_bytearray(bufx, testlen); while(1); */ while (42) { if (rfm12_rx_status() == STATUS_COMPLETE) { uint8_t len = rfm12_rx_len(); if ((len == 0) || (len % 16 != 0)) { UART_PUTF("Received garbage (%u bytes not multiple of 16): ", len); print_bytearray(bufx, len); } else // try to decrypt with all keys stored in EEPROM { bool crcok = false; for (aes_key_nr = 0; aes_key_nr < aes_key_count ; aes_key_nr++) { memcpy(bufx, rfm12_rx_buffer(), len); /*if (aes_key_nr == 0) { UART_PUTS("Before decryption: "); print_bytearray(bufx, len); }*/ e2p_basestation_get_aeskey(aes_key_nr, aes_key); //UART_PUTS("Trying AES key 2 "); //print_bytearray((uint8_t *)aes_key, 32); aes256_decrypt_cbc(bufx, len); //UART_PUTS("Decrypted bytes: "); //print_bytearray(bufx, len); crcok = pkg_header_check_crc32(len); if (crcok) { //UART_PUTS("CRC correct, AES key found!\r\n"); UART_PUTF("Received (AES key %u): ", aes_key_nr); print_bytearray(bufx, len); decode_data(len); break; } } if (!crcok) { UART_PUTS("Received garbage (CRC wrong after decryption): "); memcpy(bufx, rfm12_rx_buffer(), len); print_bytearray(bufx, len); } UART_PUTS("\r\n"); } //uart_hexdump((char *)bufcontents, rfm12_rx_len()); //UART_PUTS("\r\n"); // tell the implementation that the buffer can be reused for the next data. rfm12_rx_clear(); } // send data, if waiting in send buffer if (send_data_avail) { uint8_t i; // set AES key nr aes_key_nr = hex_to_uint8((uint8_t *)cmdbuf, 1); //UART_PUTF("AES KEY = %u\r\n", aes_key_nr); // init packet buffer memset(&bufx[0], 0, sizeof(bufx)); // set message type uint8_t message_type = hex_to_uint8((uint8_t *)cmdbuf, 3); pkg_header_set_messagetype(message_type); pkg_header_adjust_offset(); //UART_PUTF("MessageType = %u\r\n", message_type); uint8_t string_offset_data = 0; /* UART_PUTS("sKK00RRRRGGMM.............Get\r\n"); UART_PUTS("sKK01RRRRGGMMDD...........Set\r\n"); UART_PUTS("sKK02RRRRGGMMDD...........SetGet\r\n"); UART_PUTS("sKK08GGMMDD...............Status\r\n"); UART_PUTS("sKK09SSSSPPPPPPEE.........Ack\r\n"); UART_PUTS("sKK0ASSSSPPPPPPEEGGMMDD...AckStatus\r\n"); */ // set header extension fields to the values given as hex string in the user input switch (message_type) { case MESSAGETYPE_GET: case MESSAGETYPE_SET: case MESSAGETYPE_SETGET: pkg_headerext_common_set_receiverid(hex_to_uint16((uint8_t *)cmdbuf, 5)); pkg_headerext_common_set_messagegroupid(hex_to_uint8((uint8_t *)cmdbuf, 9)); pkg_headerext_common_set_messageid(hex_to_uint8((uint8_t *)cmdbuf, 11)); string_offset_data = 12; break; case MESSAGETYPE_STATUS: pkg_headerext_common_set_messagegroupid(hex_to_uint8((uint8_t *)cmdbuf, 5)); pkg_headerext_common_set_messageid(hex_to_uint8((uint8_t *)cmdbuf, 7)); string_offset_data = 8; break; case MESSAGETYPE_ACK: pkg_headerext_common_set_acksenderid(hex_to_uint16((uint8_t *)cmdbuf, 5)); pkg_headerext_common_set_ackpacketcounter(hex_to_uint24((uint8_t *)cmdbuf, 9)); pkg_headerext_common_set_error(hex_to_uint8((uint8_t *)cmdbuf, 15)); // fallthrough! case MESSAGETYPE_ACKSTATUS: pkg_headerext_common_set_messagegroupid(hex_to_uint8((uint8_t *)cmdbuf, 17)); pkg_headerext_common_set_messageid(hex_to_uint8((uint8_t *)cmdbuf, 19)); string_offset_data = 20; break; } uint8_t data_len_raw = 0; // copy message data, which exists in all packets except in Get and Ack packets if ((message_type != MESSAGETYPE_GET) && (message_type != MESSAGETYPE_ACK)) { uint8_t data_len_raw = (strlen(cmdbuf) - 1 - string_offset_data) / 2; //UART_PUTF("Data bytes = %u\r\n", data_len_raw); uint8_t start = __HEADEROFFSETBITS / 8; uint8_t shift = __HEADEROFFSETBITS % 8; // copy message data, using __HEADEROFFSETBITS value and string_offset_data for (i = 0; i < data_len_raw; i++) { uint8_t val = hex_to_uint8((uint8_t *)cmdbuf, string_offset_data + 2 * i + 1); array_write_UIntValue(start + i, shift, 8, val, bufx); } } // round packet length to x * 16 bytes uint8_t packet_len = ((uint16_t)__HEADEROFFSETBITS + (uint16_t)data_len_raw * 8) / 8; packet_len = ((packet_len - 1) / 16 + 1) * 16; // send packet which doesn't require an acknowledge immediately if ((message_type != MESSAGETYPE_GET) && (message_type != MESSAGETYPE_SET) && (message_type != MESSAGETYPE_SETGET)) { send_packet(aes_key_nr, packet_len); } else // enqueue request (don't send immediately) { // header size = 9 bytes! if (queue_request(pkg_headerext_common_get_receiverid(), message_type, aes_key_nr, bufx + 9, packet_len - 9)) { UART_PUTF("Request added to queue (%u bytes packet).\r\n", packet_len); } else { UART_PUTS("Warning! Request queue full. Packet will not be sent.\r\n"); } print_request_queue(); } // clear cmdbuf to receive more input from UART send_data_avail = false; rfm12_tick(); led_blink(200, 0, 1); } // flash LED every second to show the device is alive if (loop == 50) { led_blink(10, 10, 1); loop = 0; request_t* request = find_request_to_repeat(packetcounter + 1); if (request != 0) // if request to repeat was found in queue { UART_PUTS("Repeating request.\r\n"); send_packet((*request).aes_key, (*request).data_bytes + 9); // header size = 9 bytes! print_request_queue(); } // Auto-send something for debugging purposes... if (loop2 == 50) { //strcpy(cmdbuf, "s000102828300"); //send_data_avail = true; loop2 = 0; } else { loop2++; } } else { _delay_ms(20); } rfm12_tick(); loop++; process_rxbuf(); if (uart_timeout > 0) { uart_timeout--; if (uart_timeout == 0) { UART_PUTS("*** UART user timeout. Input was ignored. ***\r\n"); } } } // never called // aes256_done(&aes_ctx); }
int main ( void ) { uint8_t aes_key_nr; uint8_t loop = 0; uint8_t loop2 = 0; uint8_t data[22]; sbi(LED_DDR, LED_PIN); // delay 1s to avoid further communication with uart or RFM12 when my programmer resets the MC after 500ms... _delay_ms(1000); request_queue_init(); // read packetcounter, increase by cycle and write back packetcounter = eeprom_read_dword((uint32_t*)EEPROM_POS_PACKET_COUNTER) + PACKET_COUNTER_WRITE_CYCLE; eeprom_write_dword((uint32_t*)0, packetcounter); uart_init(true); UART_PUTS ("\r\n"); UART_PUTS ("Open Home Control Base Station V1.0\r\n"); UART_PUTS ("(c) 2012 Uwe Freese, www.open-home-control.com\r\n"); UART_PUTF ("Packet counter: %lu\r\n", packetcounter); UART_PUTS ("Waiting for incoming data. Press h for help.\r\n"); rfm12_init(); sei(); // ENCODE TEST /* uint8_t testlen = 64; eeprom_read_block (aes_key, (uint8_t *)EEPROM_POS_AES_KEY, 32); UART_PUTS("Using AES key "); printbytearray((uint8_t *)aes_key, 32); UART_PUTS("Before encryption: "); printbytearray(bufx, testlen); unsigned long crc = crc32(bufx, testlen); UART_PUTF("CRC32 is %lx (added as last 4 bytes)\r\n", crc); UART_PUTS("1\r\n"); crc = crc32(bufx, testlen - 4); UART_PUTS("2\r\n"); setBuf32(testlen - 4, crc); UART_PUTS("Before encryption (CRC added): "); printbytearray(bufx, testlen); UART_PUTS("1\r\n"); uint8_t aes_byte_count = aes256_encrypt_cbc(bufx, testlen); UART_PUTS("2\r\n"); UART_PUTS("After encryption: "); printbytearray(bufx, aes_byte_count); UART_PUTF("String len = %u\r\n", aes_byte_count); UART_PUTS("1\r\n"); aes256_decrypt_cbc(bufx, aes_byte_count); UART_PUTS("2\r\n"); UART_PUTS("After decryption: "); printbytearray(bufx, testlen); crc = getBuf32(testlen - 4); UART_PUTF("CRC32 is %lx (last 4 bytes from decrypted message)\r\n", crc); printbytearray(bufx, testlen); UART_PUTS("After decryption (CRC removed): "); printbytearray(bufx, testlen); UART_PUTF("String len = %u\r\n", testlen); while(1); */ while (42) { if (rfm12_rx_status() == STATUS_COMPLETE) { uint8_t len = rfm12_rx_len(); if ((len == 0) || (len % 16 != 0)) { UART_PUTF("Received garbage (%u bytes not multiple of 16): ", len); printbytearray(bufx, len); } else // try to decrypt with all keys stored in EEPROM { uint32_t assumed_crc; uint32_t actual_crc; for(aes_key_nr = 0; aes_key_nr < AES_KEY_EEPROM_COUNT ; aes_key_nr++) { //strncpy((char *)bufx, (char *)rfm12_rx_buffer(), len); memcpy(bufx, rfm12_rx_buffer(), len); /*if (aes_key_nr == 0) { UART_PUTS("Before decryption: "); printbytearray(bufx, len); }*/ eeprom_read_block (aes_key, (uint8_t *)(EEPROM_POS_AES_KEY + aes_key_nr * 32), 32); //UART_PUTS("Trying AES key "); //printbytearray((uint8_t *)aes_key, 32); aes256_decrypt_cbc(bufx, len); //UART_PUTS("Decrypted bytes: "); //printbytearray(bufx, len); assumed_crc = getBuf32(len - 4); actual_crc = crc32(bufx, len - 4); //UART_PUTF("Received CRC32 would be %lx\r\n", assumed_crc); //UART_PUTF("Re-calculated CRC32 is %lx\r\n", actual_crc); if (assumed_crc == actual_crc) { //UART_PUTS("CRC correct, AES key found!\r\n"); UART_PUTF("Received (AES key %u): ", aes_key_nr); printbytearray(bufx, len - 4); decode_data(len - 4); break; } } if (assumed_crc != actual_crc) { UART_PUTS("Received garbage (CRC wrong after decryption).\r\n"); } UART_PUTS("\r\n"); } //uart_hexdump((char *)bufcontents, rfm12_rx_len()); //UART_PUTS("\r\n"); // tell the implementation that the buffer can be reused for the next data. rfm12_rx_clear(); } // send data, if waiting in send buffer if (send_data_avail) { uint8_t i; uint8_t data_len_raw = strlen(sendbuf) / 2 - 2; // round data length to 6 + 16 bytes (including padding bytes) uint8_t data_len = (((data_len_raw + 9) / 16) + 1) * 16 - 10; // set aes key nr aes_key_nr = hex_to_uint8((uint8_t *)sendbuf, 0); //UART_PUTF("AES KEY = %u\r\n", aes_key_nr); // set command id uint8_t command_id = hex_to_uint8((uint8_t *)sendbuf, 2); // set data for (i = 0; i < data_len_raw; i++) { data[i] = hex_to_uint8((uint8_t *)sendbuf, 4 + 2 * i); } // set padding bytes for (i = data_len_raw; i < data_len; i++) { data[i] = 0; } // send status packet immediately (command IDs are less than 128) if (command_id < 128) { // set command id bufx[5] = command_id; // set data memcpy(bufx + 6, data, data_len); send_packet(aes_key_nr, data_len); } else // enqueue request (don't send immediately) { if (queue_request(data[0], command_id, aes_key_nr, data + 1)) { UART_PUTS("Adding request to queue.\r\n"); } else { UART_PUTS("Warning! Request queue full. Packet will not be sent.\r\n"); } print_request_queue(); } // clear send text buffer send_data_avail = false; rfm12_tick(); led_blink(200, 0, 1); } // flash LED every second to show the device is alive if (loop == 50) { led_blink(10, 10, 1); loop = 0; if (set_repeat_request(packetcounter + 1)) // if request to repeat was found in queue { UART_PUTS("Repeating request.\r\n"); send_packet(0, 6); print_request_queue(); } // Auto-send something for debugging purposes... if (loop2 == 50) { //strcpy(sendbuf, "008c0001003d"); //send_data_avail = true; loop2 = 0; } else { loop2++; } } else { _delay_ms(20); } rfm12_tick(); loop++; process_rxbuf(); if (uart_timeout > 0) { uart_timeout--; if (uart_timeout == 0) { UART_PUTS("*** UART user timeout. Input was ignored. ***\r\n"); } } } // never called // aes256_done(&aes_ctx); }
int main(void) { uint16_t send_status_timeout = 25; uint32_t station_packetcounter; uint32_t pos; uint8_t button_state = 0; uint8_t manual_dim_direction = 0; // delay 1s to avoid further communication with uart or RFM12 when my programmer resets the MC after 500ms... _delay_ms(1000); util_init(); check_eeprom_compatibility(DEVICE_TYPE_DIMMER); osccal_init(); // read packetcounter, increase by cycle and write back packetcounter = eeprom_read_dword((uint32_t*)EEPROM_POS_PACKET_COUNTER) + PACKET_COUNTER_WRITE_CYCLE; eeprom_write_dword((uint32_t*)EEPROM_POS_PACKET_COUNTER, packetcounter); // read device id and write to send buffer device_id = eeprom_read_byte((uint8_t*)EEPROM_POS_DEVICE_ID); use_pwm_translation = 1; //eeprom_read_byte((uint8_t*)EEPROM_POS_USE_PWM_TRANSLATION); // TODO: read (saved) dimmer state from before the eventual powerloss /*for (i = 0; i < SWITCH_COUNT; i++) { uint16_t u16 = eeprom_read_word((uint16_t*)EEPROM_POS_SWITCH_STATE + i * 2); switch_state[i] = (uint8_t)(u16 & 0b1); switch_timeout[i] = u16 >> 1; }*/ // read last received station packetcounter station_packetcounter = eeprom_read_dword((uint32_t*)EEPROM_POS_STATION_PACKET_COUNTER); led_blink(200, 200, 5); #ifdef UART_DEBUG uart_init(false); UART_PUTS ("\r\n"); UART_PUTS ("smarthomatic Dimmer V1.0 (c) 2013 Uwe Freese, www.smarthomatic.org\r\n"); osccal_info(); UART_PUTF ("Device ID: %u\r\n", device_id); UART_PUTF ("Packet counter: %lu\r\n", packetcounter); UART_PUTF ("Use PWM translation table: %u\r\n", use_pwm_translation); UART_PUTF ("Last received station packet counter: %u\r\n\r\n", station_packetcounter); #endif // init AES key eeprom_read_block (aes_key, (uint8_t *)EEPROM_POS_AES_KEY, 32); rfm12_init(); PWM_init(); io_init(); setPWMDutyCycle(0); timer0_init(); // DEMO to measure the voltages of different PWM settings to calculate the pwm_lookup table /*while (42) { uint16_t i; for (i = 0; i <= 1024; i = i + 100) { UART_PUTF ("PWM value OCR1A: %u\r\n", i); OCR1A = i; led_blink(500, 6500, 1); } }*/ // DEMO 0..100..0%, using the pwm_lookup table and the translation table in EEPROM. /*while (42) { float i; for (i = 0; i <= 100; i = i + 0.05) { led_blink(10, 10, 1); setPWMDutyCycle(i); } for (i = 99.95; i > 0; i = i - 0.05) { led_blink(10, 10, 1); setPWMDutyCycle(i); } }*/ // set initial switch state /*for (i = 0; i < SWITCH_COUNT; i++) { switchRelais(i, switch_state[i]); }*/ sei(); // DEMO 30s /*animation_length = 30; animation_length = (uint32_t)((float)animation_length * 1000 / ANIMATION_CYCLE_MS); start_brightness = 0; end_brightness = 255; animation_position = 0;*/ while (42) { if (rfm12_rx_status() == STATUS_COMPLETE) { uint8_t len = rfm12_rx_len(); if ((len == 0) || (len % 16 != 0)) { UART_PUTF("Received garbage (%u bytes not multiple of 16): ", len); printbytearray(bufx, len); } else // try to decrypt with all keys stored in EEPROM { memcpy(bufx, rfm12_rx_buffer(), len); //UART_PUTS("Before decryption: "); //printbytearray(bufx, len); aes256_decrypt_cbc(bufx, len); //UART_PUTS("Decrypted bytes: "); //printbytearray(bufx, len); uint32_t assumed_crc = getBuf32(len - 4); uint32_t actual_crc = crc32(bufx, len - 4); //UART_PUTF("Received CRC32 would be %lx\r\n", assumed_crc); //UART_PUTF("Re-calculated CRC32 is %lx\r\n", actual_crc); if (assumed_crc != actual_crc) { UART_PUTS("Received garbage (CRC wrong after decryption).\r\n"); } else { //UART_PUTS("CRC correct, AES key found!\r\n"); UART_PUTS(" Received: "); printbytearray(bufx, len - 4); // decode command and react uint8_t sender = bufx[0]; UART_PUTF(" Sender: %u\r\n", sender); if (sender != 0) { UART_PUTF("Packet not from base station. Ignoring (Sender ID was: %u).\r\n", sender); } else { uint32_t packcnt = getBuf32(1); UART_PUTF(" Packet Counter: %lu\r\n", packcnt); // check received counter if (0) //packcnt <= station_packetcounter) { UART_PUTF2("Received packet counter %lu is lower than last received counter %lu. Ignoring packet.\r\n", packcnt, station_packetcounter); } else { // write received counter station_packetcounter = packcnt; eeprom_write_dword((uint32_t*)EEPROM_POS_STATION_PACKET_COUNTER, station_packetcounter); // check command ID uint8_t cmd = bufx[5]; UART_PUTF(" Command ID: %u\r\n", cmd); if (cmd != 141) // ID 141 == Dimmer Request { UART_PUTF("Received unknown command ID %u. Ignoring packet.\r\n", cmd); } else { // check device id uint8_t rcv_id = bufx[6]; UART_PUTF(" Receiver ID: %u\r\n", rcv_id); if (rcv_id != device_id) { UART_PUTF("Device ID %u does not match. Ignoring packet.\r\n", rcv_id); } else { // read animation mode and parameters uint8_t animation_mode = bufx[7] >> 5; // TODO: Implement support for multiple dimmers (e.g. RGB) // uint8_t dimmer_bitmask = bufx[7] & 0b111; animation_length = getBuf16(8); start_brightness = bufx[10]; end_brightness = bufx[11]; UART_PUTF(" Animation Mode: %u\r\n", animation_mode); // TODO: Set binary mode like 00010110 //UART_PUTF(" Dimmer Bitmask: %u\r\n", dimmer_bitmask); UART_PUTF(" Animation Time: %us\r\n", animation_length); UART_PUTF(" Start Brightness: %u\r\n", start_brightness); UART_PUTF(" End Brightness: %u\r\n", end_brightness); animation_length = (uint32_t)((float)animation_length * 1000 / ANIMATION_CYCLE_MS); animation_position = 0; /* TODO: Write to EEPROM (?) // write back switch state to EEPROM switch_state[i] = req_state; switch_timeout[i] = req_timeout; eeprom_write_word((uint16_t*)EEPROM_POS_SWITCH_STATE + i * 2, u16); */ // send acknowledge UART_PUTS("Sending ACK:\r\n"); // set device ID (base station has ID 0 by definition) bufx[0] = device_id; // update packet counter packetcounter++; if (packetcounter % PACKET_COUNTER_WRITE_CYCLE == 0) { eeprom_write_dword((uint32_t*)0, packetcounter); } setBuf32(1, packetcounter); // set command ID "Generic Acknowledge" bufx[5] = 1; // set sender ID of request bufx[6] = sender; // set Packet counter of request setBuf32(7, station_packetcounter); // zero unused bytes bufx[11] = 0; // set CRC32 uint32_t crc = crc32(bufx, 12); setBuf32(12, crc); // show info UART_PUTF(" CRC32: %lx\r\n", crc); uart_putstr(" Unencrypted: "); printbytearray(bufx, 16); rfm12_sendbuf(); UART_PUTS(" Send encrypted: "); printbytearray(bufx, 16); UART_PUTS("\r\n"); rfm12_tick(); led_blink(200, 0, 1); send_status_timeout = 25; } } } } } } // tell the implementation that the buffer can be reused for the next data. rfm12_rx_clear(); } _delay_ms(ANIMATION_UPDATE_MS); // React on button press. // - abort animation // - switch off, when brightness > 0 // - switch on otherwise if (!(BUTTON_PORT & (1 << BUTTON_PIN))) // button press { if (button_state == 0) { UART_PUTS("Button pressed\r\n"); animation_length = 0; animation_position = 0; } if (button_state < 5) { button_state++; } else // manual dimming { if (manual_dim_direction) // UP { if (current_brightness < 100) { current_brightness = (uint8_t)current_brightness / 2 * 2 + 2; setPWMDutyCycle(current_brightness); } else { UART_PUTS("manual dimming DOWN\r\n"); manual_dim_direction = 0; } } else // DOWN { if (current_brightness > 0) { current_brightness = (((uint8_t)current_brightness - 1) / 2) * 2; setPWMDutyCycle(current_brightness); } else { UART_PUTS("manual dimming UP\r\n"); manual_dim_direction = 1; } } } } else if (button_state && (BUTTON_PORT & (1 << BUTTON_PIN))) // button release { UART_PUTS("Button released\r\n"); if (button_state < 5) // short button press { if (current_brightness > 0) { UART_PUTS(" -> 0%\r\n"); setPWMDutyCycle(0); } else { UART_PUTS(" -> 100%\r\n"); setPWMDutyCycle(100); } } else { // reverse dim direction manual_dim_direction = !manual_dim_direction; } button_state = 0; } // update brightness according animation_position, updated by timer0 if (animation_length > 0) { pos = animation_position; // copy value to avoid that it changes in between by timer interrupt UART_PUTF2("%lu/%lu, ", pos, animation_length); if (pos == animation_length) { UART_PUTF("END Brightness %u%%, ", end_brightness * 100 / 255); setPWMDutyCycle((float)end_brightness * 100 / 255); animation_length = 0; animation_position = 0; } else { float brightness = (start_brightness + ((float)end_brightness - start_brightness) * pos / animation_length) * 100 / 255; UART_PUTF("Br.%u%%, ", (uint32_t)(brightness)); setPWMDutyCycle(brightness); } } // send status from time to time if (send_status_timeout == 0) { send_status_timeout = SEND_STATUS_EVERY_SEC * (1000 / ANIMATION_UPDATE_MS); send_dimmer_status(); led_blink(200, 0, 1); } rfm12_tick(); send_status_timeout--; checkSwitchOff(); }
int RecievePacket(char* Rpacket) { /* see http://www.hansinator.de/rfm12lib/ for rfm12b libray details receive frame, send acknowledgement if received a frame: de-bytestuff check crc if recipient: acknowledge pass to network */ uint8_t* bufptr; char Rframe[50], ackstr[50]; struct frame ack; struct frame Nrframe[FRAMECOUNT]; int Received_Final_frame = 0; int i = 0; while(!Received_Final_frame){ //int Rframe_len; if (rfm12_rx_status() == STATUS_COMPLETE) { bufptr = rfm12_rx_buffer(); for(uint8_t k = 0; k < (rfm12_rx_len()); k++) { Rframe[k] = bufptr[k]; } Rframe[rfm12_rx_len()] = '\0'; rfm12_rx_clear(); put_string(Rframe); strcpy(ackstr, Rframe); int Rframe_check = decode_frame(Nrframe[i], Rframe); put_string("\nRframe_check: "); put_number(Rframe_check); if(Rframe_check & (1<<1)) { if(Rframe_check & 1<<3) { Received_Final_frame = 1; } /* frame received, frame for me acknowledge */ rfm12_tx(strlen(ackstr), 0, (uint8_t*)ackstr); for (uint8_t j = 0; j < 100; j++) { //put_string(". "); rfm12_tick(); _delay_us(500); } i++; } else if(!Rframe_check) { ; } else { break; } } } // if(i && i < FRAMECOUNT) { // put_string("\nPacketComplete"); // strcpy(Rpacket, Nrframe[0].frame); // for(int l = 1; l<i; l++) { // strcat(Rpacket, Nrframe[l].frame); // } // strcat(Rpacket, "\n"); // } return i; }
int SendPacket(char dest, char* Spacket) { /* Packet length = 122 => max 6 frames split packet into frames, send frame, await acknowledgement */ struct frame data[FRAMECOUNT]; int no_frames; put_number(millis()); put_char('\n'); no_frames = makeframe(&data, dest, Spacket, 0); put_number(millis()); put_char('\n'); uint8_t *bufptr; char temp[50]; int i,k, send_complete; struct frame ack; unsigned long time; for(i = 0; i < no_frames; i++) { send_complete = 0; char test[FRAMELEN] = "0123456789012345678901234"; while(!send_complete) { ///////////////////send////////////////////// rfm12_tx(strlen(data[i].frame), 0, (uint8_t*)data[i].frame); for (uint8_t j = 0; j < 100; j++) { //put_string(". "); rfm12_tick(); _delay_us(500); } time = millis() + 500; while((millis() != time)) { ///////////check for acknowledgemt///////////////// if(rfm12_rx_status() == STATUS_COMPLETE) { //send_complete = 1; bufptr = rfm12_rx_buffer(); for(k = 0; k < (rfm12_rx_len()); k++) { temp[k] = bufptr[k]; } temp[rfm12_rx_len()] = '\0'; rfm12_rx_clear(); // put_string("\nRECEIVED: "); // put_string(temp); // put_string("\n\n"); ////////////////check if acknowledgemnt valid//////////////// if(decode_frame(ack, temp) & (1<<1)) { //if(ack.checksum[0] == data[i].checksum[0]) { put_string("\nSend Complete!\n"); send_complete = 1; break; //} } } } if(!send_complete) { put_string("\nTIMEOUT\n"); } } } /* for frame in frames: send_complete = 0; while not send complete: send frame start timer while timer: if acknowledgement: send_complete = 1; */ return 0; }
int main(void) { uint16_t send_status_timeout = 25; uint32_t pos; uint8_t button_state = 0; uint8_t manual_dim_direction = 0; // delay 1s to avoid further communication with uart or RFM12 when my programmer resets the MC after 500ms... _delay_ms(1000); util_init(); check_eeprom_compatibility(DEVICETYPE_DIMMER); // read packetcounter, increase by cycle and write back packetcounter = e2p_generic_get_packetcounter() + PACKET_COUNTER_WRITE_CYCLE; e2p_generic_set_packetcounter(packetcounter); // read device id device_id = e2p_generic_get_deviceid(); // pwm translation table is not used if first byte is 0xFF use_pwm_translation = (0xFF != eeprom_read_UIntValue8(EEPROM_BRIGHTNESSTRANSLATIONTABLE_BYTE, EEPROM_BRIGHTNESSTRANSLATIONTABLE_BIT, 8, 0, 0xFF)); // TODO: read (saved) dimmer state from before the eventual powerloss /*for (i = 0; i < SWITCH_COUNT; i++) { uint16_t u16 = eeprom_read_word((uint16_t*)EEPROM_POS_SWITCH_STATE + i * 2); switch_state[i] = (uint8_t)(u16 & 0b1); switch_timeout[i] = u16 >> 1; }*/ // read last received station packetcounter station_packetcounter = e2p_dimmer_get_basestationpacketcounter(); led_blink(500, 500, 3); osccal_init(); uart_init(); UART_PUTS ("\r\n"); UART_PUTF4("smarthomatic Dimmer v%u.%u.%u (%08lx)\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_HASH); UART_PUTS("(c) 2013..2014 Uwe Freese, www.smarthomatic.org\r\n"); osccal_info(); UART_PUTF ("DeviceID: %u\r\n", device_id); UART_PUTF ("PacketCounter: %lu\r\n", packetcounter); UART_PUTF ("Use PWM translation table: %u\r\n", use_pwm_translation); UART_PUTF ("Last received base station PacketCounter: %u\r\n\r\n", station_packetcounter); // init AES key eeprom_read_block (aes_key, (uint8_t *)EEPROM_AESKEY_BYTE, 32); rfm12_init(); PWM_init(); io_init(); setPWMDutyCyclePercent(0); timer0_init(); // DEMO to measure the voltages of different PWM settings to calculate the pwm_lookup table /*while (42) { uint16_t i; for (i = 0; i <= 1024; i = i + 100) { UART_PUTF ("PWM value OCR1A: %u\r\n", i); OCR1A = i; led_blink(500, 6500, 1); } }*/ // DEMO 0..100..0%, using the pwm_lookup table and the translation table in EEPROM. /*while (42) { float i; for (i = 0; i <= 100; i = i + 0.05) { led_blink(10, 10, 1); setPWMDutyCycle(i); } for (i = 99.95; i > 0; i = i - 0.05) { led_blink(10, 10, 1); setPWMDutyCycle(i); } }*/ // set initial switch state /*for (i = 0; i < SWITCH_COUNT; i++) { switchRelais(i, switch_state[i]); }*/ sei(); // DEMO 30s /*animation_length = 30; animation_length = (uint32_t)((float)animation_length * 1000 / ANIMATION_CYCLE_MS); start_brightness = 0; end_brightness = 255; animation_position = 0;*/ while (42) { if (rfm12_rx_status() == STATUS_COMPLETE) { uint8_t len = rfm12_rx_len(); if ((len == 0) || (len % 16 != 0)) { UART_PUTF("Received garbage (%u bytes not multiple of 16): ", len); print_bytearray(bufx, len); } else // try to decrypt with all keys stored in EEPROM { memcpy(bufx, rfm12_rx_buffer(), len); UART_PUTS("Before decryption: "); print_bytearray(bufx, len); aes256_decrypt_cbc(bufx, len); UART_PUTS("Decrypted bytes: "); print_bytearray(bufx, len); if (!pkg_header_check_crc32(len)) { UART_PUTS("Received garbage (CRC wrong after decryption).\r\n"); } else { process_packet(len); } } // tell the implementation that the buffer can be reused for the next data. rfm12_rx_clear(); } _delay_ms(ANIMATION_UPDATE_MS); // React on button press. // - abort animation // - switch off, when brightness > 0 // - switch on otherwise if (!(BUTTON_PORT & (1 << BUTTON_PIN))) // button press { if (button_state == 0) { UART_PUTS("Button pressed\r\n"); animation_length = 0; animation_position = 0; } if (button_state < 5) { button_state++; } else // manual dimming { if (manual_dim_direction) // UP { if (current_brightness < 100) { current_brightness = (uint8_t)current_brightness / 2 * 2 + 2; setPWMDutyCyclePercent(current_brightness); } else { UART_PUTS("manual dimming DOWN\r\n"); manual_dim_direction = 0; } } else // DOWN { if (current_brightness > 0) { current_brightness = (((uint8_t)current_brightness - 1) / 2) * 2; setPWMDutyCyclePercent(current_brightness); } else { UART_PUTS("manual dimming UP\r\n"); manual_dim_direction = 1; } } } } else if (button_state && (BUTTON_PORT & (1 << BUTTON_PIN))) // button release { UART_PUTS("Button released\r\n"); if (button_state < 5) // short button press { if (current_brightness > 0) { UART_PUTS(" -> 0%\r\n"); setPWMDutyCyclePercent(0); } else { UART_PUTS(" -> 100%\r\n"); setPWMDutyCyclePercent(100); } } else { // reverse dim direction manual_dim_direction = !manual_dim_direction; } button_state = 0; } // update brightness according animation_position, updated by timer0 if (animation_length > 0) { pos = animation_position; // copy value to avoid that it changes in between by timer interrupt UART_PUTF2("%lu/%lu, ", pos, animation_length); if (pos == animation_length) { UART_PUTF("END Brightness %u%%, ", end_brightness); setPWMDutyCyclePercent((float)end_brightness); animation_length = 0; animation_position = 0; } else { float brightness = (start_brightness + ((float)end_brightness - start_brightness) * pos / animation_length); UART_PUTF("Br.%u%%, ", (uint32_t)(brightness)); setPWMDutyCyclePercent(brightness); } } // send status from time to time if (send_status_timeout == 0) { send_status_timeout = SEND_STATUS_EVERY_SEC * (1000 / ANIMATION_UPDATE_MS); send_dimmer_status(); led_blink(200, 0, 1); } else if (version_status_cycle >= SEND_VERSION_STATUS_CYCLE) { version_status_cycle = 0; send_version_status(); led_blink(200, 0, 1); } rfm12_tick(); send_status_timeout--; checkSwitchOff(); } // never called // aes256_done(&aes_ctx); }
// Zyklisches Programm void rfm12_layer2_tick() { if (rfm12_send_state == send_buffered) { // Es ist etwas zum Senden vorhanden uint8_t retval = rfm12_tx (RFM12_MYTYPE, (uint8_t*)&rfm12_send_buffer, rfm12_send_buffer.len+RFM12_SEND_HEADER_SIZE); if (retval==0x80) { // erfolgreich eingetragen rfm12_send_state = send_wait; rfm12_send_time = time_ms; debug_write_Pstr(PSTR("Packet Enqeued\r\n")); } else if ((time_ms-rfm12_send_time)>RFM12_SEND_QUEUE_TIMEOUT) { // Timeout beim Warten auf die Sendemöglichkeit // Fehlerzustand einnehmen rfm12_send_state = send_error; rfm12_send_lasterror = send_hardware; debug_write_Pstr(PSTR("SEND QUEUE TIMEOUT\r\n")); } } rfm12_tick(); if (rfm12_rx_status() == RFM12_STATUS_COMPLETE) { uint8_t rx_no_clear=0; if ((rfm12_rx_type()!=RFM12_MYTYPE) || (rfm12_rx_len()<RFM12_SEND_HEADER_SIZE)) { debug_write_Pstr(PSTR("REC INVALID\r\n")); // Paket aus anderem Protokoll oder zu kleines Paket ignorieren } else { // Flag fuer den Sendeanstoss für Antwortpakete uint8_t send_header_buffer=0; rfm12_tsend_buffer *buf = (rfm12_tsend_buffer*)rfm12_rx_buffer(); if (buf->teltype==RFM12_TELTYPE_DATANACK || (buf->destaddress==RFM12_BROADCAST_ADDRESS && buf->teltype==RFM12_TELTYPE_DATA)) { // Broadcast Empfang melden und nicht bestätigen debug_write_Pstr(PSTR("REC BROADCAST\r\n")); if (rfm12_receive_state == receive_idle) { rfm12_receive_buffer.address = buf->srcaddress; rfm12_receive_buffer.len = rfm12_rx_len()-RFM12_SEND_HEADER_SIZE; rfm12_receive_buffer.data = buf->data; rfm12_receive_state = receive_data; rx_no_clear = 1; } } else if (buf->destaddress==RFM12_MYADDRESS) { // Paket für meine Adresse switch (buf->teltype) { case RFM12_TELTYPE_DATA : // Empfang melden und bestätigen debug_write_Pstr(PSTR("REC DATA\r\n")); if (rfm12_receive_state == receive_idle) { rfm12_receive_buffer.address = buf->srcaddress; rfm12_receive_buffer.len = rfm12_rx_len()-RFM12_SEND_HEADER_SIZE; rfm12_receive_buffer.data = buf->data; rfm12_receive_state = receive_data; rx_no_clear = 1; // Antwortpaket zusammenstellen rfm12_send_header_buffer.teltype = RFM12_TELTYPE_ACK; rfm12_send_header_buffer.destaddress = buf->srcaddress; rfm12_send_header_buffer.telcount = buf->telcount; send_header_buffer=1; } break; case RFM12_TELTYPE_ACK : debug_write_Pstr(PSTR("REC ACK\r\n")); if (rfm12_send_state==send_wait && rfm12_send_buffer.destaddress==buf->srcaddress && rfm12_send_buffer.telcount==buf->telcount) { // Korrekte Bestätigung erhalten, Senden ist damit erfolgreich beendet rfm12_send_state = send_ok; } break; case RFM12_TELTYPE_NACK : debug_write_Pstr(PSTR("REC NACK\r\n")); if (rfm12_send_state==send_wait && rfm12_send_buffer.destaddress==buf->srcaddress && rfm12_send_buffer.telcount==buf->telcount) { // Ablehnung erhalten, Senden ist damit mit Fehler beendet rfm12_send_state = send_error; rfm12_send_lasterror = send_nack; } break; case RFM12_TELTYPE_PING : // Antwortpaket zusammenstellen debug_write_Pstr(PSTR("REC PING\r\n")); rfm12_send_header_buffer.teltype = RFM12_TELTYPE_PINGACK; rfm12_send_header_buffer.destaddress = buf->srcaddress; rfm12_send_header_buffer.telcount = buf->telcount; send_header_buffer=1; break; case RFM12_TELTYPE_PINGACK : debug_write_Pstr(PSTR("REC PINGACK\r\n")); if (rfm12_send_state==send_wait && rfm12_send_buffer.destaddress==buf->srcaddress && rfm12_send_buffer.telcount==buf->telcount && rfm12_send_buffer.teltype==RFM12_TELTYPE_PING) { // Korrekte Bestätigung erhalten, Ping ist damit erfolgreich beendet rfm12_send_state = send_ok; } break; case RFM12_TELTYPE_FRAGMENT : // noch nicht implementiert break; default: // alles andere wird ignoriert break; } if (send_header_buffer) { // Ein Antworttelegramm soll gesendet werden rfm12_send_header_buffer.srcaddress = RFM12_MYADDRESS; // Telegramm senden, der Rückgabewert ist uns hier egal, weil man daraus nichts ableiten kann rfm12_tx (RFM12_MYTYPE, (uint8_t*)&rfm12_send_header_buffer, RFM12_SEND_HEADER_SIZE); debug_write_Pstr(PSTR("SEND HEADER\r\n")); } } // if MYADDRESS } if (!rx_no_clear) rfm12_rx_clear(); // unterlagerten Puffer wieder freigeben } // if received if (rfm12_send_state==send_wait && (time_ms-rfm12_send_time)>RFM12_ACK_TIMEOUT) { // Timeout beim Warten auf Sendebestätigung abgelaufen debug_write_Pstr(PSTR("SEND TIMEOUT\r\n")); if (rfm12_send_buffer.retry_count++ < rfm12_send_retry_limit) { rfm12_tx (RFM12_MYTYPE, (uint8_t*)&rfm12_send_buffer, rfm12_send_buffer.len+RFM12_SEND_HEADER_SIZE); rfm12_send_time=time_ms; } else { rfm12_send_state=send_error; rfm12_send_lasterror = send_timeout; } } }