示例#1
0
文件: megaRF.cpp 项目: heye/rfm12
/***
*
*	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();
        }
    }
}
示例#4
0
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;
}
示例#5
0
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;
}
示例#6
0
void initCommunication(){
	rfm12_init();  // initialize the library
	sei();
	rfm12_rx_clear();
}
示例#7
0
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);
}
示例#8
0
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);
}
示例#9
0
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();
	}
示例#10
0
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;

}
示例#11
0
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;
}
示例#12
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);
}
示例#13
0
// 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;
    }
  }
}