MNT Reform: Open Source Portable Computer https://mntre.com/reform
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

430 lines
10KB

  1. /*
  2. NewSoftSerial.cpp
  3. Multi-instance software serial library for Arduino/Wiring
  4. -- Interrupt-driven receive and other improvements by ladyada
  5. (http://ladyada.net)
  6. -- Tuning, circular buffer, derivation from class Print/Stream,
  7. multi-instance support, porting to 8MHz processors,
  8. various optimizations, PROGMEM delay tables, inverse logic and
  9. direct port writing by Mikal Hart (http://www.arduiniana.org)
  10. -- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
  11. -- 20MHz processor support by Garrett Mace (http://www.macetech.com)
  12. -- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
  13. This library is free software; you can redistribute it and/or
  14. modify it under the terms of the GNU Lesser General Public
  15. License as published by the Free Software Foundation; either
  16. version 2.1 of the License, or (at your option) any later version.
  17. This library is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. Lesser General Public License for more details.
  21. You should have received a copy of the GNU Lesser General Public
  22. License along with this library; if not, write to the Free Software
  23. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  24. The latest version of this library can always be found at
  25. http://arduiniana.org.
  26. */
  27. #include <avr/interrupt.h>
  28. #include <avr/pgmspace.h>
  29. #include <avr/io.h>
  30. #include <stdlib.h>
  31. #include <stdbool.h>
  32. //#include "WConstants.h"
  33. //#include "pins_arduino.h"
  34. #include "serial.h"
  35. //
  36. // Lookup table
  37. //
  38. typedef struct _DELAY_TABLE
  39. {
  40. long baud;
  41. unsigned short rx_delay_centering;
  42. unsigned short rx_delay_intrabit;
  43. unsigned short rx_delay_stopbit;
  44. unsigned short tx_delay;
  45. } DELAY_TABLE;
  46. #if F_CPU == 16000000
  47. static const DELAY_TABLE PROGMEM table[] =
  48. {
  49. // baud rxcenter rxintra rxstop tx
  50. { 115200, 1, 17, 17, 12, },
  51. { 57600, 10, 37, 37, 33, },
  52. { 38400, 25, 57, 57, 54, },
  53. { 31250, 31, 70, 70, 68, },
  54. { 28800, 34, 77, 77, 74, },
  55. { 19200, 54, 117, 117, 114, },
  56. { 14400, 74, 156, 156, 153, },
  57. { 9600, 114, 236, 236, 233, },
  58. { 4800, 233, 474, 474, 471, },
  59. { 2400, 471, 950, 950, 947, },
  60. { 1200, 947, 1902, 1902, 1899, },
  61. { 300, 3804, 7617, 7617, 7614, },
  62. };
  63. const int XMIT_START_ADJUSTMENT = 5;
  64. #elif F_CPU == 8000000
  65. static const DELAY_TABLE table[] PROGMEM =
  66. {
  67. // baud rxcenter rxintra rxstop tx
  68. { 115200, 1, 5, 5, 3, },
  69. { 57600, 1, 15, 15, 13, },
  70. { 38400, 2, 25, 26, 23, },
  71. { 31250, 7, 32, 33, 29, },
  72. { 28800, 11, 35, 35, 32, },
  73. { 19200, 20, 55, 55, 52, },
  74. { 14400, 30, 75, 75, 72, },
  75. { 9600, 50, 114, 114, 112, },
  76. { 4800, 110, 233, 233, 230, },
  77. { 2400, 229, 472, 472, 469, },
  78. { 1200, 467, 948, 948, 945, },
  79. { 300, 1895, 3805, 3805, 3802, },
  80. };
  81. const int XMIT_START_ADJUSTMENT = 4;
  82. #error This version of NewSoftSerial supports only 16 and 8MHz processors
  83. #endif
  84. #define HIGH 1
  85. #define LOW 0
  86. // per object data
  87. uint8_t _receivePin;
  88. uint8_t _receiveBitMask;
  89. volatile uint8_t *_receivePortRegister;
  90. uint8_t _transmitBitMask;
  91. volatile uint8_t *_transmitPortRegister;
  92. uint16_t _rx_delay_centering;
  93. uint16_t _rx_delay_intrabit;
  94. uint16_t _rx_delay_stopbit;
  95. uint16_t _tx_delay;
  96. uint16_t _buffer_overflow=1;
  97. uint16_t _inverse_logic=1;
  98. // static data
  99. static char _receive_buffer[_SS_MAX_RX_BUFF];
  100. static volatile uint8_t _receive_buffer_tail;
  101. static volatile uint8_t _receive_buffer_head;
  102. // public only for easy access by interrupt handlers
  103. static inline void ser_handle_interrupt(void);
  104. //
  105. // Private methods
  106. //
  107. /* static */
  108. inline void ser_tunedDelay(uint16_t delay) {
  109. uint8_t tmp=0;
  110. register uint16_t dly asm("r24") = delay;
  111. asm volatile("sbiw %0, 0x01 \n\t"
  112. "ldi %1, 0xFF \n\t"
  113. "cpi %A0, 0xFF \n\t"
  114. "cpc %B0, %1 \n\t"
  115. "brne .-10 \n\t"
  116. : "+r" (dly), "+a" (tmp)
  117. : "0" (dly)
  118. );
  119. }
  120. bool _listening = false;
  121. bool ser_listen()
  122. {
  123. _buffer_overflow = false;
  124. uint8_t oldSREG = SREG;
  125. cli();
  126. _receive_buffer_head = _receive_buffer_tail = 0;
  127. SREG = oldSREG;
  128. _listening = true;
  129. return true;
  130. }
  131. //
  132. // The receive routine called by the interrupt handler
  133. //
  134. void ser_recv()
  135. {
  136. uint8_t d = 0;
  137. // If RX line is high, then we don't see any start bit
  138. // so interrupt is probably not for us
  139. if (_inverse_logic ? ser_rx_pin_read() : !ser_rx_pin_read())
  140. {
  141. // Wait approximately 1/2 of a bit width to "center" the sample
  142. ser_tunedDelay(_rx_delay_centering);
  143. // Read each of the 8 bits
  144. for (uint8_t i=0x1; i; i <<= 1)
  145. {
  146. ser_tunedDelay(_rx_delay_intrabit);
  147. uint8_t noti = ~i;
  148. if (ser_rx_pin_read())
  149. d |= i;
  150. else // else clause added to ensure function timing is ~balanced
  151. d &= noti;
  152. }
  153. // skip the stop bit
  154. ser_tunedDelay(_rx_delay_stopbit);
  155. if (_inverse_logic)
  156. d = ~d;
  157. // if buffer full, set the overflow flag and return
  158. if ((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head)
  159. {
  160. // save new data in buffer: tail points to where byte goes
  161. _receive_buffer[_receive_buffer_tail] = d; // save new byte
  162. _receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
  163. }
  164. else
  165. {
  166. _buffer_overflow = true;
  167. }
  168. }
  169. }
  170. void ser_tx_pin_write(uint8_t pin_state)
  171. {
  172. if (pin_state == LOW) {
  173. //*_transmitPortRegister &= ~_transmitBitMask;
  174. PORTB &= ~(1<<7);
  175. } else {
  176. PORTB |= (1<<7);
  177. //*_transmitPortRegister |= _transmitBitMask;
  178. }
  179. }
  180. uint8_t ser_rx_pin_read()
  181. {
  182. return (PINE&(1<<6));
  183. //return *_receivePortRegister & _receiveBitMask;
  184. }
  185. //
  186. // Interrupt handling
  187. //
  188. static inline void ser_handle_interrupt()
  189. {
  190. ser_recv();
  191. }
  192. ISR(INT6_vect)
  193. {
  194. ser_handle_interrupt();
  195. }
  196. //
  197. // Constructor
  198. //
  199. void ser_init(volatile uint8_t* rx_port, uint8_t rx_pin, volatile uint8_t* tx_port, uint8_t tx_pin, bool inverse_logic)
  200. {
  201. _rx_delay_centering = 0;
  202. _rx_delay_intrabit = 0;
  203. _rx_delay_stopbit = 0;
  204. _tx_delay = 0;
  205. _buffer_overflow = false;
  206. _inverse_logic = inverse_logic;
  207. ser_set_tx(rx_port, rx_pin);
  208. ser_set_rx(rx_port, rx_pin);
  209. }
  210. bool ser_is_listening() {
  211. return _listening;
  212. }
  213. bool ser_overflow() {
  214. bool ret = _buffer_overflow;
  215. _buffer_overflow = false;
  216. return ret;
  217. }
  218. #define output_low(port,pin) *port &= ~(1<<pin)
  219. #define output_high(port,pin) *port |= (1<<pin)
  220. void ser_set_tx(volatile uint8_t* port, uint8_t pin)
  221. {
  222. output_high(port, pin);
  223. //digitalWrite(tx, HIGH);
  224. _transmitBitMask = (1<<pin);
  225. _transmitPortRegister = port;
  226. }
  227. void ser_set_rx(volatile uint8_t* port, uint8_t pin)
  228. {
  229. //if (!_inverse_logic)
  230. // digitalWrite(rx, HIGH); // pullup for normal logic!
  231. //_receivePin = rx;
  232. _receiveBitMask = (1<<pin);
  233. _receivePortRegister = port;
  234. }
  235. //
  236. // Public methods
  237. //
  238. void ser_begin(long speed)
  239. {
  240. _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
  241. for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i)
  242. {
  243. long baud = pgm_read_dword(&table[i].baud);
  244. if (baud == speed)
  245. {
  246. _rx_delay_centering = pgm_read_word(&table[i].rx_delay_centering);
  247. _rx_delay_intrabit = pgm_read_word(&table[i].rx_delay_intrabit);
  248. _rx_delay_stopbit = pgm_read_word(&table[i].rx_delay_stopbit);
  249. _tx_delay = pgm_read_word(&table[i].tx_delay);
  250. break;
  251. }
  252. }
  253. // Set up RX interrupts, but only if we have a valid RX baud rate
  254. if (_rx_delay_stopbit)
  255. {
  256. //PCICR |= 1; // enable pin change interrupt
  257. EICRB = (1<<4); // ISC60: Any logical change on INT6 generates an interrupt request
  258. EIMSK |= (1<<6); // INT6 unmask
  259. ser_tunedDelay(_tx_delay); // if we were low this establishes the end
  260. }
  261. ser_listen();
  262. }
  263. void ser_end()
  264. {
  265. // TODO disable interrupts
  266. EICRB = 0;
  267. }
  268. // Read data from buffer
  269. int ser_read()
  270. {
  271. if (!ser_is_listening())
  272. return -1;
  273. // Empty buffer?
  274. if (_receive_buffer_head == _receive_buffer_tail)
  275. return -1;
  276. // Read from "head"
  277. uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
  278. _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
  279. return d;
  280. }
  281. int ser_available()
  282. {
  283. if (!ser_is_listening())
  284. return 0;
  285. return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
  286. }
  287. void ser_write(uint8_t b)
  288. {
  289. if (_tx_delay == 0)
  290. return;
  291. uint8_t oldSREG = SREG;
  292. cli(); // turn off interrupts for a clean txmit
  293. // Write the start bit
  294. ser_tx_pin_write(_inverse_logic ? HIGH : LOW);
  295. ser_tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);
  296. // Write each of the 8 bits
  297. if (_inverse_logic)
  298. {
  299. for (uint8_t mask = 0x01; mask; mask <<= 1)
  300. {
  301. if (b & mask) // choose bit
  302. ser_tx_pin_write(LOW); // send 1
  303. else
  304. ser_tx_pin_write(HIGH); // send 0
  305. ser_tunedDelay(_tx_delay);
  306. }
  307. ser_tx_pin_write(LOW); // restore pin to natural state
  308. }
  309. else
  310. {
  311. for (uint8_t mask = 0x01; mask; mask <<= 1)
  312. {
  313. if (b & mask) // choose bit
  314. ser_tx_pin_write(HIGH); // send 1
  315. else
  316. ser_tx_pin_write(LOW); // send 0
  317. ser_tunedDelay(_tx_delay);
  318. }
  319. ser_tx_pin_write(HIGH); // restore pin to natural state
  320. }
  321. SREG = oldSREG; // turn interrupts back on
  322. ser_tunedDelay(_tx_delay);
  323. }
  324. #if !defined(cbi)
  325. #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  326. #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  327. #endif
  328. void ser_enable_timer0(bool enable)
  329. {
  330. if (enable)
  331. #if defined(__AVR_ATmega8__)
  332. sbi(TIMSK, TOIE0);
  333. #else
  334. sbi(TIMSK0, TOIE0);
  335. #endif
  336. else
  337. #if defined(__AVR_ATmega8__)
  338. cbi(TIMSK, TOIE0);
  339. #else
  340. cbi(TIMSK0, TOIE0);
  341. #endif
  342. }
  343. void ser_flush()
  344. {
  345. uint8_t oldSREG = SREG;
  346. cli();
  347. _receive_buffer_head = _receive_buffer_tail = 0;
  348. SREG = oldSREG;
  349. }
  350. int ser_peek()
  351. {
  352. // Empty buffer?
  353. if (_receive_buffer_head == _receive_buffer_tail)
  354. return -1;
  355. // Read from "head"
  356. return _receive_buffer[_receive_buffer_head];
  357. }