Last active
August 21, 2016 00:23
-
-
Save Girgitt/834750ba8459662a051f8b1704289033 to your computer and use it in GitHub Desktop.
A draft implementation of a multi-master strategy over RS485 "auto-tx" PHY for PJON protocol stack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ThroughHardwareSerialRs485AutoTx enables PJON multi-master communication through the Serial port with auto-tx RS485 PHY. | |
Work based on ThroughHardwareSerial by Giovanni Blu Mitolo and Fred Larsen | |
Copyright (c) 2016 by Zbigniew Zasieczny All rights reserved. | |
With rs485 "auto-tx" PHY the hardware serial port reads everything sent to the bus | |
The "self-reading" property could be used in this strategy to detect colisions at a byte-level in a similar way the CAN network works on a bit-level to silelntly drop-off lower priority nodes; feature not implemented yet | |
A naive timeout-based collision avoidance is used: bus is assumed clear for tx within specified time window after empty rx buffer was detected. The receive(<timeout_us>) function must be called often - transimission would occur only within 1ms after last receive call on empty rx buffer; within this time window the update() function must be called to transmit packets. | |
*/ | |
#include <Arduino.h> | |
#define THROUGH_HARDWARE_SERIAL_MAX_TIME 500 // Wait up to 5 ms to receive a byte | |
#define THROUGH_HARDWARE_SERIAL_MIN_CHANNEL_SILELNCE_WINDOW 100 // min 1 ms silence to start sending | |
class ThroughHardwareSerialRs485AutoTx { | |
public: | |
HardwareSerial *serial; | |
/* Pass the Serial port where you want to operate with */ | |
void set_serial(HardwareSerial *serial_port) { | |
serial = serial_port; | |
}; | |
/* Returns the Serial object value i.e. if(Serial) */ | |
boolean can_start(uint8_t input_pin, uint8_t output_pin) { | |
if (micros() - _last_clear_channel_ts < THROUGH_HARDWARE_SERIAL_MIN_CHANNEL_SILELNCE_WINDOW ) return false; | |
return (serial != NULL) && *serial; // Check if pointer | |
}; | |
/* Send a byte and wait for its transmission end */ | |
void send_byte(uint8_t b, uint8_t input_pin, uint8_t output_pin) { | |
serial->write(b); | |
serial->flush(); | |
//if (receive_byte(input_pin, output_pin) != b) return FAIL; // needs additional work with logic analyzer; sent byte should be avaialbe in rx buffer immediatelly but isn't | |
//return 0; | |
}; | |
/* Try to receive a byte with a maximum waiting time */ | |
uint16_t receive_byte(uint8_t input_pin, uint8_t output_pin) { | |
uint32_t time = micros(); | |
while(micros() - time < THROUGH_HARDWARE_SERIAL_MAX_TIME) | |
if(serial->available() > 0) | |
return (uint8_t)serial->read(); | |
_last_clear_channel_ts = micros(); | |
return FAIL; | |
}; | |
/* Receive byte response */ | |
uint16_t receive_response(uint8_t input_pin, uint8_t output_pin) { | |
return receive_byte(input_pin, output_pin); | |
}; | |
/* Send byte response to the packet's transmitter */ | |
void send_response(uint8_t response, uint8_t input_pin, uint8_t output_pin) { | |
send_byte(response, input_pin, output_pin); | |
}; | |
private: | |
long _last_clear_channel_ts; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment