//NCE_Bus_Probe.cpp Implementation File#include "NCE_Bus_Probe.h"
SoftwareSerial RS485(12,11); //Rx Tx
NCE_Bus_Probe :: NCE_Bus_Probe ( uint8_t my_address) {_my_address = 0x80+my_address; };
void NCE_Bus_Probe::begin (uint8_t tt ){ _trace = tt; RS485.begin(9600); int count = 0; while (!RS485.available( )) {if (count<50) //do not saturate screen with dots. {Serial.print("."); count++;}} Serial.println("\nRS485 Available"); while (get_NCE_Byte( ) != 0x80){ }; //synchronise with broadcast address wait_for_myaddress( ); Serial.print("\nMy Address on reset "); Send2Bytes485(0x7E,0x7F); Serial.print("Send 7E-7F: "); uint8_t rxByte = get_NCE_Byte( ); if (rxByte == 0xD2) {SendByteRS485('a'); //dumb terminal Serial.println("\nResponse 'a' == Dumb terminal. ");} else _handle_mess(rxByte); _send_buffer[0]= 0; _buffer_ptr = 0; _buffer_full = 0;
}//----------------------------
//Need to implement the method that will point the library routine to the required client operation//Client will call this as part of initialisation
void NCE_Bus_Probe::setMessHandler(MessHandler clientPtr) { MessHandlerFn = clientPtr; }
//----------------------------------------------------------- void NCE_Bus_Probe::_output_message( ) { //(uint8_t len) {
//This will be part of the Broadcast State and part of ItsMe state. if (MessHandlerFn) //if client has not set up link this code is skipped MessHandlerFn(_ping, _BusBuffer[0],_BusBuffer[1],_BusBuffer[2],_BusBuffer[3],_BusBuffer[4],_BusBuffer[5],_BusBuffer[6], _BusBuffer[7], _BusBuffer[8]);
if (_bufflen == 9) { if (_trace) { Serial.print("Message"); for (int i=1; i<= _bufflen; i++){ Serial.print(" "); Serial.print(char(_BusBuffer[i])); } Serial.println(); } } } //--------------------------------------------------------------------------------
//NCE does not use straight ASCII code - this routine adjusts
uint8_t NCE_Bus_Probe::_NCE_ASCII(uint8_t rr){
if (rr & 0x20) return (rr & 0x3F); else return (rr & 0x7F);}//-------------------------------------------------------uint8_t NCE_Bus_Probe:: _handle_mess(uint8_t rxByte){ if ((rxByte >= 0xC0)&& (rxByte <= 0xC7)) _bufflen=9; else if ((rxByte ==0xCE)||(rxByte==0xCF)) _bufflen= 1; else _bufflen = 2; if (_trace) { Serial.print("Message rxByte = "); Serial.print(rxByte,HEX); Serial.print(" length = "); Serial.println(_bufflen,HEX); Serial.print("Raw message "); } _BusBuffer[0] = rxByte; _BusPtr = 1; while(_BusPtr < _bufflen){ if (_bufflen == 9 ){ rxByte = get_NCE_Byte(); _BusBuffer[_BusPtr++] = _NCE_ASCII(rxByte); // Serial.print(rxByte,HEX); Serial.print(','); } else _BusBuffer[_BusPtr++] = get_NCE_Byte(); //load buffer } // Serial.println(); _output_message(); return get_NCE_Byte( ); } //----------------------------
void NCE_Bus_Probe ::_its_me(){ start_timer = millis( ); if (_buffer_full) { //there's a request to send if (_buffer_ptr ==0){ //first byte of request Send2Bytes485(_send_buffer[0],0x7F); Serial.print("Request "); Serial.println(_send_buffer[0],HEX); _buffer_ptr++; } else //following bytes of request if (_mess_count < 20){ //hold off outputting next byte _mess_count++; I_AM_HERE; } else { //count ==20 send out the next byte Serial.print(" Send "); Serial.println(_send_buffer[_buffer_ptr],HEX); Send2Bytes485(_send_buffer[_buffer_ptr++],0x7F); _mess_count = 0; //start the delay if (_buffer_ptr == _buffer_size) _buffer_full = 0; //all done } } else //buffer empty - nothing to send if (_trace) Serial.println("I'm here send 0x7D 0x7F"); I_AM_HERE; //no requests } //------------------------------------------------- void NCE_Bus_Probe ::wait_for_myaddress(){ uint8_t rxByte; /* * Could get here in unsyncronised entry but should * Will also enter here after doing whatever for myaddress */ rxByte = get_NCE_Byte(); //will be next ping but could be a message to my address while (rxByte != _my_address) //will not do loop if myaddress { if BUS_PING rxByte = get_NCE_Byte(); //next ping else { //its a message Serial.print(" mess "); Serial.print(rxByte,HEX);Serial.print(" "); rxByte = _handle_mess(rxByte); } } _its_me(); //do whatever for myaddress //will exit before reading any messages //should read message on next loop } //-------------------------------------------------------- uint8_t NCE_Bus_Probe::get_NCE_Byte( ) { uint8_t rxByte; while (!RS485.available( )); rxByte = RS485.read(); if BUS_PING _ping = rxByte; //save ping of interest if (_trace){ if (rxByte == 0x80) Serial.println(); //sync to broadcast if (rxByte < 16) Serial.print('0'); Serial.print(rxByte,HEX); Serial.print(' '); } return rxByte; }
//digital writes required if using RS485 device with separate Tx enable.//It appears a delay of 200 microseconds is required. 100 will not work
void NCE_Bus_Probe::SendByteRS485(uint8_t mess){ //delayMicroseconds(200); while (millis() < start_timer + 200); RS485.write(mess);}void NCE_Bus_Probe::Send2Bytes485(uint8_t m1,uint8_t m2) {// delayMicroseconds(200); while (millis() < start_timer + 200); RS485.write(m1); RS485.write(m2); } //--------------------------------------------------------- void NCE_Bus_Probe::macro(int mac){ if (_buffer_full) return; Serial.println("Loading Buffer"); _send_buffer[0] = 0x5C; _send_buffer[1] = 0x50+ mac/100; mac %= 100; _send_buffer[2] = 0x50+ mac/10; mac %= 10; _send_buffer[3] = 0x50+ mac; _send_buffer[4] = 0x40; _buffer_ptr = 0; _buffer_size = 5; _buffer_full = 1; } bool NCE_Bus_Probe::free2send(){ return (!_buffer_full); }