@ -7,121 +7,138 @@
@@ -7,121 +7,138 @@
# include "SoftRS485.h"
//#define DEBUG
# define IDLE -1
# define START -2
# define MSG_LEN 64
# define IDLE 0
# define START 1
# define RECEIVING 2
# define SENDING 3
# define COMPLETE 4
// Pins
int _RO , _RE , _DE , _DI ;
int _idle_cycles = 0 ;
/* INCOMING */
byte _recv_byte = 0x0 ;
char _recv_message [ MSG_LEN ] ;
byte _recv_byte = 0x00 ;
byte _recv_state = IDLE ;
boolean _recv_bit = false ;
char _recv_message [ MSG_LEN ] ;
int _recv_idx = 0 ; // used as bit-index for _recv_byte
int _recv_pos = IDLE ; // used as char-index for _recv_message
byte _recv_idx = 0 ;
int _recv_pos = 0 ;
/* OUTGOING */
char _message_out [ MSG_LEN ] ;
int _send_pos = IDLE ;
int _send_idx = 0 ;
char _send_message [ MSG_LEN ] ;
boolean _send_bit = false ;
byte _send_state = IDLE ;
byte _send_wait = 0 ;
byte _send_idx = 0 ;
int _send_pos = 0 ;
ISR ( TIMER1_COMPA_vect ) {
OCR1A + = 62500 ; // Advance The COMPA Register
OCR1A + = 3228 ; // Advance The COMPA Register
_recv_bit = ! digitalRead ( _RO ) ; // input line is HIGH by default
if ( _recv_pos = = IDLE ) {
if ( _recv_bit ) { // first 1 indicates incoming message
_recv_pos = 0 ;
if ( _send_state = = SENDING ) {
char c = _send_message [ _send_pos ] ;
_send_bit = c & 1 < < _send_idx ;
digitalWrite ( _DI , ! _send_bit ) ;
# ifdef DEBUG
Serial . println ( F ( " start of message reception " ) ) ;
Serial . print ( " Sending bit " ) ; Serial . print ( _send_idx ) ; Serial . print ( " of " ) ; Serial . print ( c ) ; Serial . print ( " : " ) ; Serial . print ( _send_bit ) ; Serial . print ( " / " ) ;
# endif
_send_idx + + ;
if ( _send_idx = = 8 ) { // byte completed
_send_pos + + ; // advance to next byte
_send_idx = 0 ; // start with first bit
if ( c = = 0x00 | | _send_idx = = MSG_LEN ) { // we just send a 0-byte
_send_state = COMPLETE ;
}
}
} else { // we are reading!
_recv_byte | = _recv_bit < < _recv_idx ;
# ifdef DEBUG
Serial . print ( F ( " received bit # " ) ) ;
Serial . print ( _recv_idx ) ;
Serial . print ( " : " ) ;
Serial . println ( _recv_bit ) ;
Serial . print ( F ( " byte is now " ) ) ;
Serial . println ( _recv_byte , BIN ) ;
# endif
if ( _recv_idx = = 7 ) { // byte complete
# ifdef DEBUG
Serial . print ( F ( " byte complete: " ) ) ;
Serial . println ( _recv_byte ) ;
# endif
_recv_idx = 0 ;
_recv_message [ _recv_pos ] = _recv_byte ;
if ( _recv_byte = = 0x00 ) { // we encountered a 0-byte! End of message!
}
if ( _send_state = = START & & _idle_cycles > 9 ) {
_send_bit = HIGH ;
digitalWrite ( _DE , HIGH ) ;
digitalWrite ( _DI , ! _send_bit ) ;
_send_state = SENDING ;
_send_idx = 0 ;
_send_pos = 0 ;
# ifdef DEBUG
Serial . print ( F ( " got 0-byte! \n message reception complete: " ) ) ;
Serial . println ( _recv_message ) ;
Serial . print ( " Sent start bit: " ) ; Serial . print ( _send_bit ) ; Serial . print ( " / " ) ;
# endif
_recv_idx = 0 ;
_recv_pos = IDLE ;
} else {
_recv_byte = 0x00 ;
if ( _recv_pos < MSG_LEN - 1 ) {
_recv_pos + + ;
}
}
} else _recv_idx + + ;
}
boolean bit = LOW ;
_recv_bit = ! digitalRead ( _RO ) ; // LOW = 1
if ( _send_pos > = 0 ) {
char c = _message_out [ _send_pos ] ;
if ( c = = 0x00 ) { // end of message
digitalWrite ( _DI , HIGH ) ;
digitalWrite ( _DE , LOW ) ;
_send_pos = IDLE ;
_send_idx = 0 ;
_message_out [ 0 ] = 0x00 ;
if ( _recv_bit ) {
_idle_cycles = 0 ;
} else if ( _idle_cycles < 1000 ) {
_idle_cycles + + ;
}
# ifdef DEBUG
Serial . println ( " Message transmission completed! " ) ;
Serial . print ( " idle cycles: " ) ; Serial . print ( _idle_cycles ) ; Serial . print ( " / " ) ;
Serial . print ( " received: " ) ; Serial . print ( _recv_bit ) ; Serial . print ( " / " ) ;
# endif
} else {
bit = ! ( c & 1 < < _send_idx ) ;
digitalWrite ( _DI , bit ) ;
if ( _send_bit ! = _recv_bit & & _send_state = = SENDING ) { // collision while sending
digitalWrite ( _DE , LOW ) ; // disable driver
_send_state = START ; // start over
_idle_cycles = 0 ;
# ifdef DEBUG
Serial . print ( " Sending bit # " ) ;
Serial . print ( _send_idx ) ;
Serial . print ( " ( " ) ;
Serial . print ( bit ) ;
Serial . print ( " ) of " ) ;
Serial . print ( c ) ;
Serial . print ( " ( " ) ;
Serial . print ( c , BIN ) ;
Serial . println ( " ) " ) ;
Serial . println ( " \n COLLISION " ) ;
# endif
_send_idx + + ;
if ( _send_idx > 7 ) {
_send_idx = 0 ;
_send_pos + + ;
}
}
}
if ( _send_pos = = START & & _recv_pos = = IDLE & & _message_out [ 0 ] ! = 0x00 ) { // outgoig message awaits, line is idle
digitalWrite ( _DE , HIGH ) ; // enable driver
if ( _send_state = = COMPLETE ) {
digitalWrite ( _DE , LOW ) ; // disable driver
_send_message [ 0 ] = 0x00 ; // clear message
_send_state = IDLE ;
_idle_cycles = 0 ;
# ifdef DEBUG
Serial . println ( F ( " starting transmission " ) ) ;
Serial . print ( " transmission complete / " ) ;
# endif
digitalWrite ( _DI , bit ) ; // send start bit
_send_pos = 0 ;
}
if ( _send_pos ! = IDLE & & digitalRead ( _RO ) ! = bit ) { // driver output state mismatch!
digitalWrite ( _DE , LOW ) ; // disable driver
_send_pos = START ;
if ( _recv_state = = START ) {
_recv_byte = 0x00 ;
_recv_pos = 0 ;
_recv_idx = 0 ;
_recv_state = RECEIVING ;
# ifdef DEBUG
Serial . println ( F ( " collision! " ) ) ;
Serial . print ( " Start reception / " ) ;
# endif
}
if ( _recv_bit & & _recv_state = = IDLE ) {
_recv_state = START ;
}
if ( _recv_state = = RECEIVING ) {
_recv_byte | = _recv_bit < < _recv_idx ; // set bit
_recv_idx + + ; // increase bit index
if ( _recv_idx = = 8 ) { // byte full
# ifdef DEBUG
Serial . print ( " pushing " ) ; Serial . print ( ( char ) _recv_byte ) ; Serial . print ( " / " ) ;
# endif
_recv_message [ _recv_pos ] = _recv_byte ; // push character to string
if ( _recv_byte = = 0x00 ) { // end of message
_recv_state = IDLE ;
# ifdef DEBUG
Serial . print ( " reception complete: " ) ; Serial . print ( _recv_message ) ;
# endif
}
_recv_idx = 0 ; // start new byte
_recv_byte = 0 ;
_recv_pos + + ; // goto next string pos
if ( _recv_pos = = MSG_LEN ) _recv_pos - - ; // avoid overflow
}
}
# ifdef DEBUG
Serial . println ( ) ;
# endif
}
void init485 ( int RO , int nRE , int DE , int DI ) {
@ -130,7 +147,7 @@ void init485(int RO, int nRE, int DE, int DI){
@@ -130,7 +147,7 @@ void init485(int RO, int nRE, int DE, int DI){
_DE = DE ;
_DI = DI ;
_recv_message [ 0 ] = 0x00 ; // empty
_message_out [ 0 ] = 0x00 ; // empty
_send_ message [ 0 ] = 0x00 ; // empty
pinMode ( _RO , INPUT ) ;
pinMode ( _RE , OUTPUT ) ;
@ -144,8 +161,8 @@ void init485(int RO, int nRE, int DE, int DI){
@@ -144,8 +161,8 @@ void init485(int RO, int nRE, int DE, int DI){
TCCR1A = 0 ; // Init Timer1A
TCCR1B = 0 ; // Init Timer1B
TCCR1B | = B00000001 ; // Prescaler = 5 12
OCR1A = 500 ; // Timer Compare1A Register
TCCR1B | = B00000001 ; // Prescaler = 1
OCR1A = 3328 ; // Timer Compare1A Register
TIMSK1 | = B00000010 ; // Enable Timer COMPA Interrupt
# ifdef DEBUG
Serial . begin ( 115200 ) ;
@ -162,7 +179,7 @@ void init485(int RO, int nRE, int DE, int DI){
@@ -162,7 +179,7 @@ void init485(int RO, int nRE, int DE, int DI){
}
boolean available485 ( ) {
return _recv_po s = = IDLE & & _recv_message [ 0 ] ! = 0 ;
return _recv_state = = IDLE & & _recv_message [ 0 ] ! = 0 ;
}
String get485Message ( ) {
@ -172,17 +189,16 @@ String get485Message(){
@@ -172,17 +189,16 @@ String get485Message(){
}
boolean send485 ( char message [ ] ) {
if ( _message_out [ 0 ] ! = 0x00 ) return false ; // we already have a queued message, abort!
if ( _send_ message [ 0 ] ! = 0x00 ) return false ; // we already have a queued message, abort!
for ( int idx = 0 ; idx < MSG_LEN ; idx + + ) {
_message_out [ idx ] = message [ idx ] ; // copy message
_send_ message [ idx ] = message [ idx ] ; // copy message
if ( message [ idx ] = = 0x00 ) break ;
}
if ( _message_out [ 0 ] = = 0x00 ) return false ; // message is empty! abort
_send_po s = START ;
if ( _send_ message [ 0 ] = = 0x00 ) return false ; // message is empty! abort
_send_state = START ;
# ifdef DEBUG
Serial . print ( " sending " ) ;
Serial . println ( _message_out ) ;
Serial . print ( " sending " ) ; Serial . println ( _send_message ) ;
# endif
return true ;
}