My Marlin configs for Fabrikator Mini and CTC i3 Pro B
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.

SoftwareSerial.cpp 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. SoftwareSerial.cpp (formerly 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. #ifdef TARGET_LPC1768
  28. //
  29. // Includes
  30. //
  31. //#include <WInterrupts.h>
  32. #include "../../inc/MarlinConfig.h"
  33. #include <stdint.h>
  34. #include <stdarg.h>
  35. #include "arduino.h"
  36. #include "pinmapping.h"
  37. #include "fastio.h"
  38. #include "SoftwareSerial.h"
  39. void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode);
  40. void GpioDisableInt(uint32_t port, uint32_t pin);
  41. //
  42. // Statics
  43. //
  44. SoftwareSerial *SoftwareSerial::active_object = 0;
  45. unsigned char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF];
  46. volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
  47. volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;
  48. typedef struct _DELAY_TABLE
  49. {
  50. long baud;
  51. uint16_t rx_delay_centering;
  52. uint16_t rx_delay_intrabit;
  53. uint16_t rx_delay_stopbit;
  54. uint16_t tx_delay;
  55. } DELAY_TABLE;
  56. // rough delay estimation
  57. static const DELAY_TABLE table[] =
  58. {
  59. //baud |rxcenter|rxintra |rxstop |tx
  60. { 250000, 2, 4, 4, 4, }, //Done but not good due to instruction cycle error
  61. { 115200, 4, 8, 8, 8, }, //Done but not good due to instruction cycle error
  62. //{ 74880, 69, 139, 62, 162, }, // estimation
  63. // { 57600, 100, 185, 1, 208, }, // Done but not good due to instruction cycle error
  64. //{ 38400, 13, 26, 26, 26, }, // Done
  65. //{ 19200, 26, 52, 52, 52, }, // Done
  66. { 9600, 52, 104, 104, 104, }, // Done
  67. //{ 4800, 104, 208, 208, 208, },
  68. //{ 2400, 208, 417, 417, 417, },
  69. //{ 1200, 416, 833, 833, 833,},
  70. };
  71. //
  72. // Private methods
  73. //
  74. #if 0
  75. /* static */
  76. inline void SoftwareSerial::tunedDelay(uint32_t count) {
  77. asm volatile(
  78. "mov r3, %[loopsPerMicrosecond] \n\t" //load the initial loop counter
  79. "1: \n\t"
  80. "sub r3, r3, #1 \n\t"
  81. "bne 1b \n\t"
  82. ://empty output list
  83. :[loopsPerMicrosecond] "r" (count)
  84. :"r3", "cc" //clobber list
  85. );
  86. }
  87. #else
  88. inline void SoftwareSerial::tunedDelay(uint32_t count) {
  89. delayMicroseconds(count);
  90. }
  91. #endif
  92. // This function sets the current object as the "listening"
  93. // one and returns true if it replaces another
  94. bool SoftwareSerial::listen()
  95. {
  96. if (!_rx_delay_stopbit)
  97. return false;
  98. if (active_object != this)
  99. {
  100. if (active_object)
  101. active_object->stopListening();
  102. _buffer_overflow = false;
  103. _receive_buffer_head = _receive_buffer_tail = 0;
  104. active_object = this;
  105. setRxIntMsk(true);
  106. return true;
  107. }
  108. return false;
  109. }
  110. // Stop listening. Returns true if we were actually listening.
  111. bool SoftwareSerial::stopListening()
  112. {
  113. if (active_object == this)
  114. {
  115. setRxIntMsk(false);
  116. active_object = NULL;
  117. return true;
  118. }
  119. return false;
  120. }
  121. //
  122. // The receive routine called by the interrupt handler
  123. //
  124. void SoftwareSerial::recv()
  125. {
  126. uint8_t d = 0;
  127. // If RX line is high, then we don't see any start bit
  128. // so interrupt is probably not for us
  129. if (_inverse_logic ? rx_pin_read() : !rx_pin_read())
  130. {
  131. // Disable further interrupts during reception, this prevents
  132. // triggering another interrupt directly after we return, which can
  133. // cause problems at higher baudrates.
  134. setRxIntMsk(false);//__disable_irq();//
  135. // Wait approximately 1/2 of a bit width to "center" the sample
  136. tunedDelay(_rx_delay_centering);
  137. // Read each of the 8 bits
  138. for (uint8_t i=8; i > 0; --i)
  139. {
  140. tunedDelay(_rx_delay_intrabit);
  141. d >>= 1;
  142. if (rx_pin_read())
  143. d |= 0x80;
  144. }
  145. if (_inverse_logic)
  146. d = ~d;
  147. // if buffer full, set the overflow flag and return
  148. uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
  149. if (next != _receive_buffer_head)
  150. {
  151. // save new data in buffer: tail points to where byte goes
  152. _receive_buffer[_receive_buffer_tail] = d; // save new byte
  153. _receive_buffer_tail = next;
  154. }
  155. else
  156. {
  157. _buffer_overflow = true;
  158. }
  159. tunedDelay(_rx_delay_stopbit);
  160. // Re-enable interrupts when we're sure to be inside the stop bit
  161. setRxIntMsk(true);//__enable_irq();//
  162. }
  163. }
  164. uint32_t SoftwareSerial::rx_pin_read()
  165. {
  166. return digitalRead(_receivePin);
  167. }
  168. //
  169. // Interrupt handling
  170. //
  171. /* static */
  172. inline void SoftwareSerial::handle_interrupt()
  173. {
  174. if (active_object)
  175. {
  176. active_object->recv();
  177. }
  178. }
  179. extern "C" void intWrapper() {
  180. SoftwareSerial::handle_interrupt();
  181. }
  182. //
  183. // Constructor
  184. //
  185. SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) :
  186. _rx_delay_centering(0),
  187. _rx_delay_intrabit(0),
  188. _rx_delay_stopbit(0),
  189. _tx_delay(0),
  190. _buffer_overflow(false),
  191. _inverse_logic(inverse_logic)
  192. {
  193. setTX(transmitPin);
  194. setRX(receivePin);
  195. }
  196. //
  197. // Destructor
  198. //
  199. SoftwareSerial::~SoftwareSerial()
  200. {
  201. end();
  202. }
  203. void SoftwareSerial::setTX(uint8_t tx)
  204. {
  205. // First write, then set output. If we do this the other way around,
  206. // the pin would be output low for a short while before switching to
  207. // output hihg. Now, it is input with pullup for a short while, which
  208. // is fine. With inverse logic, either order is fine.
  209. digitalWrite(tx, _inverse_logic ? LOW : HIGH);
  210. pinMode(tx,OUTPUT);
  211. _transmitPin = tx;
  212. }
  213. void SoftwareSerial::setRX(uint8_t rx)
  214. {
  215. pinMode(rx, INPUT_PULLUP); // pullup for normal logic!
  216. //if (!_inverse_logic)
  217. // digitalWrite(rx, HIGH);
  218. _receivePin = rx;
  219. _receivePort = LPC1768_PIN_PORT(rx);
  220. _receivePortPin = LPC1768_PIN_PIN(rx);
  221. /* GPIO_T * rxPort = digitalPinToPort(rx);
  222. _receivePortRegister = portInputRegister(rxPort);
  223. _receiveBitMask = digitalPinToBitMask(rx);*/
  224. }
  225. //
  226. // Public methods
  227. //
  228. void SoftwareSerial::begin(long speed)
  229. {
  230. _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
  231. for(uint8_t i = 0; i < sizeof(table)/sizeof(table[0]); ++i)
  232. {
  233. long baud = table[i].baud;
  234. if(baud == speed)
  235. {
  236. _rx_delay_centering = table[i].rx_delay_centering;
  237. _rx_delay_intrabit = table[i].rx_delay_intrabit;
  238. _rx_delay_stopbit = table[i].rx_delay_stopbit;
  239. _tx_delay = table[i].tx_delay;
  240. break;
  241. }
  242. }
  243. attachInterrupt(_receivePin, intWrapper, CHANGE); //this->handle_interrupt, CHANGE);
  244. listen();
  245. tunedDelay(_tx_delay);
  246. }
  247. void SoftwareSerial::setRxIntMsk(bool enable)
  248. {
  249. if (enable)
  250. GpioEnableInt(_receivePort,_receivePin,CHANGE);
  251. else
  252. GpioDisableInt(_receivePort,_receivePin);
  253. }
  254. void SoftwareSerial::end()
  255. {
  256. stopListening();
  257. }
  258. // Read data from buffer
  259. int SoftwareSerial::read()
  260. {
  261. if (!isListening())
  262. return -1;
  263. // Empty buffer?
  264. if (_receive_buffer_head == _receive_buffer_tail)
  265. return -1;
  266. // Read from "head"
  267. uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
  268. _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
  269. return d;
  270. }
  271. int SoftwareSerial::available()
  272. {
  273. if (!isListening())
  274. return 0;
  275. return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
  276. }
  277. size_t SoftwareSerial::write(uint8_t b)
  278. {
  279. // By declaring these as local variables, the compiler will put them
  280. // in registers _before_ disabling interrupts and entering the
  281. // critical timing sections below, which makes it a lot easier to
  282. // verify the cycle timings
  283. bool inv = _inverse_logic;
  284. uint16_t delay = _tx_delay;
  285. if(inv)
  286. b = ~b;
  287. cli(); // turn off interrupts for a clean txmit
  288. // Write the start bit
  289. if (inv)
  290. digitalWrite(_transmitPin, 1);
  291. else
  292. digitalWrite(_transmitPin, 0);
  293. tunedDelay(delay);
  294. // Write each of the 8 bits
  295. for (uint8_t i = 8; i > 0; --i)
  296. {
  297. if (b & 1) // choose bit
  298. digitalWrite(_transmitPin, 1); // send 1 //(GPIO_Desc[_transmitPin].P)->DOUT |= GPIO_Desc[_transmitPin].bit;
  299. else
  300. digitalWrite(_transmitPin, 0); // send 0 //(GPIO_Desc[_transmitPin].P)->DOUT &= ~GPIO_Desc[_transmitPin].bit;
  301. tunedDelay(delay);
  302. b >>= 1;
  303. }
  304. // restore pin to natural state
  305. if (inv)
  306. digitalWrite(_transmitPin, 0);
  307. else
  308. digitalWrite(_transmitPin, 1);
  309. sei(); // turn interrupts back on
  310. tunedDelay(delay);
  311. return 1;
  312. }
  313. void SoftwareSerial::flush()
  314. {
  315. if (!isListening())
  316. return;
  317. cli();
  318. _receive_buffer_head = _receive_buffer_tail = 0;
  319. sei();
  320. }
  321. int SoftwareSerial::peek()
  322. {
  323. if (!isListening())
  324. return -1;
  325. // Empty buffer?
  326. if (_receive_buffer_head == _receive_buffer_tail)
  327. return -1;
  328. // Read from "head"
  329. return _receive_buffer[_receive_buffer_head];
  330. }
  331. #endif // TARGET_LPC1768