//
// ZigBee module common operations library
//
// Department of Mechatronics
// Tallinn University of Technology
// © Copyrights 2011
//

//
// Take use of delay functions
//
#include <util/delay.h>

//
// String operations
//
#include <string.h>

//
// Take use of USART functions
//
#include "usart.h"

//
// Include zigbee.h for definitions
//
#include "module/zigbee.h"

//
// Finds other ZigBee modules around and saves their addresses into 'nodelist' array
//
void zigbee_find_nodes(usart port, zigbee_node_t *nodelist, uint8_t maxlen)
{
    char buf[10];
	uint8_t i;

	// wait for guard time and some more, to be use not to get any info
    _delay_ms(1200);

	// send "+++" for module to enter into command mode and accepting "AT" commands
    usart_send_string(port, "+++");
	// wait for "OK\r" from module accepting command
    usart_read_string(port, buf, 10);

	// manually add the general address 0x000000000000FFFF that all modules will react to
    strncpy(nodelist->address64h, "00000000", 9);
    strncpy(nodelist->address64l, "0000FFFF", 9);
    
	// send "Node Discovery" command to ZigBee module to receive info about other modules around
    usart_send_string(port, "ATND\r");

    for (i=1; i<maxlen; i++)
    {
		// first line not important, miss it
        usart_read_string(port, buf, 10);
        if (buf[0] == 0) break;
            

		// read higher 32 bits of address
        usart_read_string(port, buf, 10);
        if (buf[0] == 0) break;

        // save into array
        strncpy((nodelist+i)->address64h, buf, 9);
        
		// read lower 32 bits of address
        usart_read_string(port, buf, 10);
        if (buf[0] == 0) break;
            

        // save into array
        strncpy((nodelist+i)->address64l, buf, 9);
        
		// read all other unimportant lines
        do usart_read_string(port, buf, 10);
        while (buf[0] != 0);
    }

	// lower bit of the last address is zero to indicate the end of array
    (nodelist+i)->address64l[0] = 0;

    // set packetization timeout
    usart_send_string(port, "ATRO 0\r");
    usart_read_string(port, buf, 10);

	// set ZigBee module back to data mode
    usart_send_string(port, "ATCN\r");
    usart_read_string(port, buf, 10);
}

//
// Set ZigBee module to send & receive data to chosen other ZigBee node
//
void zigbee_set_destination(usart port, zigbee_node_t *node)
{
    char buf[10];

	// if low address is zero, then exit
    if (node->address64l[0] == 0)
        return;

	// wait guard time + some more
    _delay_ms(1200);

    // enter command mode
    usart_send_string(port, "+++");
    usart_read_string(port, buf, 10);

	// set high address
    usart_send_string(port, "ATDH ");
    usart_send_string(port, node->address64h);
    usart_send_string(port, "\r");
    usart_read_string(port, buf, 10);

    // set low address
    usart_send_string(port, "ATDL ");
    usart_send_string(port, node->address64l);
    usart_send_string(port, "\r");
    usart_read_string(port, buf, 10);

    // go back to data mode
    usart_send_string(port, "ATCN\r");
    usart_read_string(port, buf, 10);
}

//
// writes address list of other discovered ZigBee modules into LCD
//
void zigbee_lcd_show_nodes(uint8_t startline, zigbee_node_t *nodelist, uint8_t maxlen)
{
    for (uint8_t i=0; i<maxlen; i++)
    {
        // until address64l is zero
        if ((nodelist+i)->address64l[0] == 0)
            break;

        // write to LCD
        lcd_gfx_goto_char_xy(0, startline+i);
        lcd_gfx_write_string((nodelist+i)->address64l);
    }
}
