Advertisement
zykes

Untitled

May 9th, 2017
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.31 KB | None | 0 0
  1.  
  2. /* ThroughSerial digital communication data link layer
  3. used as a Strategy by the PJON framework (included in version v4.1)
  4.  
  5. Contributors:
  6. - Fred Larsen, Development, testing and debugging
  7. - Zbigniew Zasieczny, collision avoidance multi-drop RS485 (latency)
  8. and SoftwareSerial compatibility
  9. - Franketto (Arduino forum user) RS485 TX enable pin compatibility
  10. ____________________________________________________________________________
  11.  
  12. ThroughSerial, copyright 2016-2017 by Giovanni Blu Mitolo All rights reserved
  13.  
  14. Licensed under the Apache License, Version 2.0 (the "License");
  15. you may not use this file except in compliance with the License.
  16. You may obtain a copy of the License at
  17.  
  18. http://www.apache.org/licenses/LICENSE-2.0
  19.  
  20. Unless required by applicable law or agreed to in writing, software
  21. distributed under the License is distributed on an "AS IS" BASIS,
  22. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  23. See the License for the specific language governing permissions and
  24. limitations under the License. */
  25.  
  26. #pragma once
  27.  
  28. #include "Timing.h"
  29.  
  30. class ThroughSerial {
  31. public:
  32. #if defined(ARDUINO)
  33. Stream *serial = NULL;
  34. #elif defined(RPI)
  35. int16_t serial = 0;
  36. #elif defined(WINX86)
  37. Serial *serial = NULL;
  38. #endif
  39. /* Returns the suggested delay related to the attempts passed as parameter: */
  40.  
  41. uint32_t back_off(uint8_t attempts) {
  42. uint32_t result = attempts;
  43. for(uint8_t d = 0; d < TS_BACK_OFF_DEGREE; d++)
  44. result *= (uint32_t)(attempts);
  45. return result;
  46. };
  47.  
  48. /* Begin method, to be called before transmission or reception:
  49. (returns always true) */
  50.  
  51. bool begin(uint8_t additional_randomness = 0) {
  52. PJON_DELAY_MICROSECONDS(
  53. PJON_RANDOM(TS_INITIAL_DELAY) + additional_randomness
  54. );
  55. return true;
  56. };
  57.  
  58.  
  59. /* Check if the channel is free for transmission: */
  60.  
  61. bool can_start() {
  62. PJON_DELAY_MICROSECONDS(PJON_RANDOM(TS_COLLISION_DELAY));
  63. if(PJON_SERIAL_AVAILABLE(serial)) return false;
  64. if((uint32_t)(PJON_MICROS() - _last_reception_time) < TS_TIME_IN)
  65. return false;
  66. return true;
  67. };
  68.  
  69.  
  70. /* Returns the maximum number of attempts for each transmission: */
  71.  
  72. static uint8_t get_max_attempts() {
  73. return TS_MAX_ATTEMPTS;
  74. };
  75.  
  76.  
  77. /* Handle a collision: */
  78.  
  79. void handle_collision() {
  80. PJON_DELAY_MICROSECONDS(PJON_RANDOM(TS_COLLISION_DELAY));
  81. };
  82.  
  83.  
  84. /* Try to receive a byte with a maximum waiting time */
  85.  
  86. uint16_t receive_byte(uint32_t time_out = TS_BYTE_TIME_OUT) {
  87. uint32_t time = PJON_MICROS();
  88. while((uint32_t)(PJON_MICROS() - time) < time_out)
  89. if(PJON_SERIAL_AVAILABLE(serial)) {
  90. _last_reception_time = PJON_MICROS();
  91. uint16_t read = (uint8_t)PJON_SERIAL_READ(serial);
  92. if(read >= 0) return read;
  93. }
  94. return PJON_FAIL;
  95. };
  96.  
  97.  
  98. /* Receive byte response */
  99.  
  100. uint16_t receive_response() {
  101. return receive_byte(TS_RESPONSE_TIME_OUT);
  102. };
  103.  
  104.  
  105. /* Receive a string: */
  106.  
  107. uint16_t receive_string(uint8_t *string, uint16_t max_length) {
  108. uint16_t result = receive_byte();
  109. if(result == PJON_FAIL) return PJON_FAIL;
  110. *string = result;
  111. return 1;
  112. };
  113.  
  114.  
  115. /* Send a byte and wait for its transmission end */
  116.  
  117. void send_byte(uint8_t b) {
  118. PJON_SERIAL_WRITE(serial, b);
  119. };
  120.  
  121.  
  122. /* Send byte response to the packet's transmitter */
  123.  
  124. void send_response(uint8_t response) {
  125. _start_tx();
  126.  
  127. send_byte(response);
  128. PJON_SERIAL_FLUSH(serial);
  129.  
  130. _end_tx();
  131. };
  132.  
  133.  
  134. /* Send a string: */
  135.  
  136. void send_string(uint8_t *string, uint8_t length) {
  137. _start_tx();
  138. for(uint8_t b = 0; b < length; b++)
  139. send_byte(string[b]);
  140. PJON_SERIAL_FLUSH(serial);
  141. _end_tx();
  142. };
  143.  
  144.  
  145. /* Pass the Serial port where you want to operate with */
  146.  
  147. #if defined(ARDUINO)
  148. void set_serial(Stream *serial_port) {
  149. #elif defined(RPI)
  150. void set_serial(int16_t serial_port) {
  151. #elif defined(WINX86)
  152. void set_serial(Serial *serial_port) {
  153. #endif
  154. serial = serial_port;
  155. };
  156.  
  157. /* Pass the enable transmission pin for RS485 if in use */
  158. void set_enable_RS485_pin(uint8_t pin) {
  159. set_rx_RS485_pin(pin);
  160. };
  161.  
  162. void set_rx_RS485_pin(uint8_t pin) {
  163. _enable_rx_RS485_pin = pin;
  164. PJON_IO_MODE(_enable_rx_RS485_pin, OUTPUT);
  165. };
  166.  
  167. void set_tx_RS485_pin(uint8_t pin) {
  168. _enable_tx_RS485_pin = pin;
  169. PJON_IO_MODE(_enable_tx_RS485_pin, OUTPUT);
  170. };
  171.  
  172. private:
  173. void _start_tx() {
  174. PJON_IO_WRITE(_enable_tx_RS485_pin, HIGH);
  175. if (_enable_rx_RS485_pin != PJON_NOT_ASSIGNED && _enable_rx_RS485_pin != _enable_tx_RS485_pin) {
  176. PJON_IO_WRITE(_enable_rx_RS485_pin, HIGH);
  177. }
  178. }
  179.  
  180. void _end_tx() {
  181. PJON_IO_WRITE(_enable_tx_RS485_pin, LOW);
  182. if (_enable_rx_RS485_pin != PJON_NOT_ASSIGNED && _enable_rx_RS485_pin != _enable_tx_RS485_pin) {
  183. PJON_IO_WRITE(_enable_rx_RS485_pin, LOW);
  184. }
  185. }
  186. uint32_t _last_reception_time;
  187. uint8_t _enable_rx_RS485_pin = PJON_NOT_ASSIGNED;
  188. uint8_t _enable_tx_RS485_pin = PJON_NOT_ASSIGNED;
  189. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement