/*! \file edp.c \brief Emerald Data Protocol System. */ //***************************************************************************** // // File Name : 'edp.c' // Title : Emerald Data Protocol System // Author : Pascal Stang - Copyright (C) 2003 // Created : 2003.07.01 // Revised : 2003.07.21 // Version : 0.1 // Target MCU : Atmel AVR series // Editor Tabs : 4 // // This code is distributed under the GNU Public License // which can be found at http://www.gnu.org/licenses/gpl.txt // //***************************************************************************** //----- Include Files --------------------------------------------------------- #include // include I/O definitions (port names, pin names, etc) #include // include "signal" names (interrupt names) #include // include interrupt support #include // include program-space support #include "global.h" // include our global settings #include "i2c.h" // include I2C support #include "rprintf.h" // include printf function library #include "edp.h" // globals // EDP master/command: response code and reply buffer u08 EdpCommandResponseCode; //u08 EdpCommandReplyLength; u08 EdpCommandReplyBuffer[EDP_REPLY_BUFFER_SIZE]; u08 EdpCommandReplyChecksum; // EDP slave: response code and reply buffer u08 EdpSlaveResponseCode; u08 EdpSlaveReplyLength; u08 EdpSlaveReplyBuffer[EDP_REPLY_BUFFER_SIZE]; // EDP slave request handler function pointer EdpSlaveHandlerFuncType edpSlaveHandlerFunc; // functions void edpInit(void) { // initialize i2c interface and function library i2cInit(); // set i2c bit rate to 30KHz i2cSetBitrate(30); // set the Slave Receive Handler function // (this function will run whenever a master somewhere else on the bus // writes data to us as a slave) i2cSetSlaveReceiveHandler( edpSlaveReceiveService ); // set the Slave Transmit Handler function // (this function will run whenever a master somewhere else on the bus // attempts to read data from us as a slave) i2cSetSlaveTransmitHandler( edpSlaveTransmitService ); } void edpSetSlaveHandler(EdpSlaveHandlerFuncType edpSlaveHandlerFunction) { edpSlaveHandlerFunc = edpSlaveHandlerFunction; } // ************ EDP Master operations ************ u08 edpSendCommand(u08 deviceAddr, u08 cmdLength, EdpCommand* edpCommand) { EdpReply* edpCommandReply = (EdpReply*)EdpCommandReplyBuffer; u08* sendData; u08* replyData; u08 replyLength; u08 checksum; // initialize response variables edpCommandReply->Length = 0; EdpCommandReplyChecksum = 0; #ifdef EDP_DEBUG rprintf("\r\nBegin EdpSendCommand, TWSR:0x%x\r\n",inb(TWSR)); #endif // disable TWI interrupt cbi(TWCR, TWIE); // clear TWI interface //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)); // send start condition i2cSendStart(); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Start, TWSR:0x%x\r\n",inb(TWSR)); #endif // send device address with write i2cSendByte( (deviceAddr&0xFE) ); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Device Address+Write, TWSR:0x%x\r\n",inb(TWSR)); #endif // check if device is present and live if( i2cGetStatus() != TW_MT_SLA_ACK) { // device did not ACK it's address, command will not continue // transmit stop condition // leave with TWEA on for slave receiving i2cSendStop(); while( !(inb(TWCR) & BV(TWSTO)) ); #ifdef EDP_DEBUG rprintf("No Device!, Sent Stop, TWSR:0x%x\r\n",inb(TWSR)); #endif // enable TWI interrupt sbi(TWCR, TWIE); // return error return EDP_COMMAND_NODEV; } // send data sendData = (u08*)edpCommand; checksum = 0; while(cmdLength) { i2cSendByte( *sendData ); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Data, TWSR:0x%x\r\n",inb(TWSR)); #endif checksum += *sendData++; cmdLength--; } // send the checksum i2cSendByte( ~checksum ); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Checksum, TWSR:0x%x\r\n",inb(TWSR)); #endif // send repeated start condition i2cSendStart(); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Repeated Start, TWSR:0x%x\r\n",inb(TWSR)); #endif // send device address with read i2cSendByte( deviceAddr|0x01 ); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Device Address+Read, TWSR:0x%x\r\n",inb(TWSR)); #endif // read response code, return NACK i2cReceiveByte(FALSE); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Read Data, TWSR:0x%x\r\n",inb(TWSR)); #endif EdpCommandResponseCode = i2cGetReceivedByte(); if(EdpCommandResponseCode==EDP_RESP_DATA_REPLY) { // a data reply is being sent // send repeated start condition i2cSendStart(); i2cWaitForComplete(); // send device address with read i2cSendByte( deviceAddr|0x01 ); i2cWaitForComplete(); // get length, return ACK i2cReceiveByte(TRUE); i2cWaitForComplete(); edpCommandReply->Length = i2cGetReceivedByte(); // set temp variables replyLength = edpCommandReply->Length; replyData = edpCommandReply->Data; // get data, return ACKs // preset checksum with the datalength byte checksum = replyLength; while(replyLength > 1) { i2cReceiveByte(TRUE); // receive data byte and return ACK i2cWaitForComplete(); *replyData = i2cGetReceivedByte(); checksum += *replyData++; replyLength--; } // get last data (actually the checksum), return NACK (last-byte signal) i2cReceiveByte(FALSE); i2cWaitForComplete(); *replyData = i2cGetReceivedByte(); // add received checksum+1 to our checksum, the result should be zero checksum += (*replyData) + 1; // save the reply checksum EdpCommandReplyChecksum = checksum; } // transmit stop condition // leave with TWEA on for slave receiving i2cSendStop(); while( !(inb(TWCR) & BV(TWSTO)) ); #ifdef EDP_DEBUG rprintf("Sent Stop, TWSR:0x%x\r\n",inb(TWSR)); #endif // enable TWI interrupt sbi(TWCR, TWIE); return EDP_COMMAND_OK; } // get the response code and reply from last command u08 edpGetCommandReply(u08* responseCode, EdpReply** edpReply) { u08 retval=EDP_REPLY_OK; // get the response code from last command *responseCode = EdpCommandResponseCode; // get the reply from last command *edpReply = (EdpReply*)EdpCommandReplyBuffer; // check response code if(EdpCommandResponseCode == EDP_RESP_DATA_REPLY) { // there was a reply, check the checksum // if it's non-zero, data corruption is present if(EdpCommandReplyChecksum) retval = EDP_REPLY_BADCHKSUM; } return retval; } /* u08 edpSendCommand(u08 deviceAddr, u08 sendLength, u08* sendData) { u08* replyData = EdpCommandReplyBuffer; u08 replyLength; u08 checksum; // initialize response variables EdpCommandReplyLength = 0; EdpCommandReplyChecksum = 0; #ifdef EDP_DEBUG rprintf("\r\nBegin EdpSendCommand, TWSR:0x%x\r\n",inb(TWSR)); #endif // disable TWI interrupt cbi(TWCR, TWIE); // clear TWI interface //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)); // send start condition i2cSendStart(); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Start, TWSR:0x%x\r\n",inb(TWSR)); #endif // send device address with write i2cSendByte( (deviceAddr&0xFE) ); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Device Address+Write, TWSR:0x%x\r\n",inb(TWSR)); #endif // check if device is present and live if( i2cGetStatus() != TW_MT_SLA_ACK) { // device did not ACK it's address, command will not continue // transmit stop condition // leave with TWEA on for slave receiving i2cSendStop(); while( !(inb(TWCR) & BV(TWSTO)) ); #ifdef EDP_DEBUG rprintf("No Device!, Sent Stop, TWSR:0x%x\r\n",inb(TWSR)); #endif // enable TWI interrupt sbi(TWCR, TWIE); // return error return EDP_COMMAND_NODEV; } // send data checksum = 0; while(sendLength) { i2cSendByte( *sendData ); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Data, TWSR:0x%x\r\n",inb(TWSR)); #endif checksum += *sendData++; sendLength--; } // send the checksum i2cSendByte( ~checksum ); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Checksum, TWSR:0x%x\r\n",inb(TWSR)); #endif // send repeated start condition i2cSendStart(); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Repeated Start, TWSR:0x%x\r\n",inb(TWSR)); #endif // send device address with read i2cSendByte( deviceAddr|0x01 ); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Sent Device Address+Read, TWSR:0x%x\r\n",inb(TWSR)); #endif // read response code, return NACK i2cReceiveByte(FALSE); i2cWaitForComplete(); #ifdef EDP_DEBUG rprintf("Read Data, TWSR:0x%x\r\n",inb(TWSR)); #endif EdpCommandResponseCode = i2cGetReceivedByte(); if(EdpCommandResponseCode==EDP_RESP_DATA_REPLY) { // a data reply is being sent // send repeated start condition i2cSendStart(); i2cWaitForComplete(); // send device address with read i2cSendByte( deviceAddr|0x01 ); i2cWaitForComplete(); // get length, return ACK i2cReceiveByte(TRUE); i2cWaitForComplete(); replyLength = i2cGetReceivedByte(); EdpCommandReplyLength = replyLength; // get data, return ACKs // preset checksum with the datalength byte checksum = replyLength; while(replyLength > 1) { i2cReceiveByte(TRUE); // receive data byte and return ACK i2cWaitForComplete(); *replyData = i2cGetReceivedByte(); checksum += *replyData++; replyLength--; } // get last data (actually the checksum), return NACK (last-byte signal) i2cReceiveByte(FALSE); i2cWaitForComplete(); *replyData = i2cGetReceivedByte(); // add received checksum+1 to our checksum, the result should be zero checksum += (*replyData) + 1; // save the reply checksum EdpCommandReplyChecksum = checksum; } // transmit stop condition // leave with TWEA on for slave receiving i2cSendStop(); while( !(inb(TWCR) & BV(TWSTO)) ); #ifdef EDP_DEBUG rprintf("Sent Stop, TWSR:0x%x\r\n",inb(TWSR)); #endif // enable TWI interrupt sbi(TWCR, TWIE); return EDP_COMMAND_OK; } u08 edpGetCommandReply(u08* responseCode, u08* replyLength, u08** replyData) { u08 retval=EDP_REPLY_OK; // get the response code and reply data from last command *responseCode = EdpCommandResponseCode; // get the reply length from last command *replyLength = EdpCommandReplyLength; // get the reply data from last command *replyData = EdpCommandReplyBuffer; // check response code if(EdpCommandResponseCode == EDP_RESP_DATA_REPLY) { // there was a reply, check the checksum // if it's non-zero, data corruption is present if(EdpCommandReplyChecksum) retval = EDP_REPLY_BADCHKSUM; } return retval; } */ // ************ EDP Slave operations ************ // this function will run when a master somewhere else on the bus // addresses us and wishes to write data to us void edpSlaveReceiveService(u08 receiveDataLength, u08* receiveData) { u08 i,checksum; // initialize the reply length from this command EdpSlaveReplyLength = 0; // verify the checksum // initialize the checksum with 1 checksum = 0x01; // sum all the data in the packet and the data's checksum for(i=0; iLength+1; // initialize checksum checksum = edpReply->Length+1; // copy reply buffer to the transmit buffer for(i=0; iLength; i++) { *transmitData++ = edpReply->Data[i]; checksum += edpReply->Data[i]; } // copy checksum to transmit buffer *transmitData++ = ~checksum; // set number of bytes to transmit transmitDataLength = edpReply->Length+2; } // return number of bytes written to transmit buffer return transmitDataLength; }