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.

преди 11 години
преди 10 години
преди 11 години
преди 10 години
преди 11 години
преди 10 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 9 години
преди 11 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /* USB API for Teensy USB Development Board
  2. * http://www.pjrc.com/teensy/teensyduino.html
  3. * Copyright (c) 2008 PJRC.COM, LLC
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. */
  23. #include <avr/io.h>
  24. #include <stdint.h>
  25. #include "usb_common.h"
  26. #include "usb_private.h"
  27. #include "usb_api.h"
  28. #include "wiring.h"
  29. // Public Methods //////////////////////////////////////////////////////////////
  30. void usb_serial_class::begin(long speed)
  31. {
  32. // make sure USB is initialized
  33. peek_buf = -1;
  34. usb_init();
  35. uint16_t begin_wait = (uint16_t)millis();
  36. while (1) {
  37. // wait for the host to finish enumeration
  38. if (usb_configuration) {
  39. delay(200); // a little time for host to load a driver
  40. return;
  41. }
  42. // or for suspend mode (powered without USB)
  43. if (usb_suspended) {
  44. uint16_t begin_suspend = (uint16_t)millis();
  45. while (usb_suspended) {
  46. // must remain suspended for a while, because
  47. // normal USB enumeration causes brief suspend
  48. // states, typically under 0.1 second
  49. if ((uint16_t)millis() - begin_suspend > 250) {
  50. return;
  51. }
  52. }
  53. }
  54. // ... or a timout (powered by a USB power adaptor that
  55. // wiggles the data lines to keep a USB device charging)
  56. if ((uint16_t)millis() - begin_wait > 2500) return;
  57. }
  58. }
  59. void usb_serial_class::end()
  60. {
  61. usb_shutdown();
  62. delay(25);
  63. }
  64. // number of bytes available in the receive buffer
  65. int usb_serial_class::available()
  66. {
  67. uint8_t n=0, i, intr_state;
  68. intr_state = SREG;
  69. cli();
  70. if (usb_configuration) {
  71. UENUM = CDC_RX_ENDPOINT;
  72. n = UEBCLX;
  73. if (!n) {
  74. i = UEINTX;
  75. if (i & (1<<RXOUTI) && !(i & (1<<RWAL))) UEINTX = 0x6B;
  76. }
  77. }
  78. SREG = intr_state;
  79. if (peek_buf >= 0 && n < 255) n++;
  80. return n;
  81. }
  82. int usb_serial_class::peek()
  83. {
  84. if (peek_buf < 0) peek_buf = read();
  85. return peek_buf;
  86. }
  87. // get the next character, or -1 if nothing received
  88. int usb_serial_class::read(void)
  89. {
  90. uint8_t c, intr_state;
  91. if (peek_buf >= 0) {
  92. c = peek_buf;
  93. peek_buf = -1;
  94. return c;
  95. }
  96. // interrupts are disabled so these functions can be
  97. // used from the main program or interrupt context,
  98. // even both in the same program!
  99. intr_state = SREG;
  100. cli();
  101. if (!usb_configuration) {
  102. SREG = intr_state;
  103. return -1;
  104. }
  105. UENUM = CDC_RX_ENDPOINT;
  106. retry:
  107. c = UEINTX;
  108. if (!(c & (1<<RWAL))) {
  109. // no data in buffer
  110. if (c & (1<<RXOUTI)) {
  111. UEINTX = 0x6B;
  112. goto retry;
  113. }
  114. SREG = intr_state;
  115. return -1;
  116. }
  117. // take one byte out of the buffer
  118. c = UEDATX;
  119. // if this drained the buffer, release it
  120. if (!(UEINTX & (1<<RWAL))) UEINTX = 0x6B;
  121. SREG = intr_state;
  122. return c;
  123. }
  124. size_t usb_serial_class::readBytes(char *buffer, size_t length)
  125. {
  126. size_t count=0;
  127. unsigned long startMillis;
  128. uint8_t num, intr_state;
  129. startMillis = millis();
  130. if (length <= 0) return 0;
  131. if (peek_buf >= 0) {
  132. *buffer++ = peek_buf;
  133. peek_buf = -1;
  134. length--;
  135. if (length == 0) return 1;
  136. count = 1;
  137. }
  138. do {
  139. intr_state = SREG;
  140. cli();
  141. if (!usb_configuration) {
  142. SREG = intr_state;
  143. break;
  144. }
  145. UENUM = CDC_RX_ENDPOINT;
  146. if (!(UEINTX & (1<<RXOUTI))) {
  147. SREG = intr_state;
  148. break;
  149. }
  150. num = UEBCLX;
  151. if (num > length) num = length;
  152. for (uint8_t i=0; i < num; i++) {
  153. *buffer++ = UEDATX; // TODO: unroll loop for speed
  154. }
  155. if (!(UEINTX & (1<<RWAL))) UEINTX = 0x6B;
  156. SREG = intr_state;
  157. count += num;
  158. length -= num;
  159. if (length == 0) return count;
  160. } while(millis() - startMillis < _timeout);
  161. setReadError();
  162. return count;
  163. }
  164. void usb_serial_class::flush()
  165. {
  166. send_now();
  167. }
  168. // discard any buffered input
  169. void usb_serial_class::clear()
  170. {
  171. uint8_t intr_state;
  172. if (usb_configuration) {
  173. intr_state = SREG;
  174. cli();
  175. UENUM = CDC_RX_ENDPOINT;
  176. while ((UEINTX & (1<<RWAL))) {
  177. UEINTX = 0x6B;
  178. }
  179. SREG = intr_state;
  180. }
  181. peek_buf = -1;
  182. }
  183. #if 0
  184. // transmit a character.
  185. void usb_serial_class::write(uint8_t c)
  186. {
  187. uint8_t timeout, intr_state;
  188. // if we're not online (enumerated and configured), error
  189. if (!usb_configuration) return;
  190. // interrupts are disabled so these functions can be
  191. // used from the main program or interrupt context,
  192. // even both in the same program!
  193. intr_state = SREG;
  194. cli();
  195. UENUM = CDC_TX_ENDPOINT;
  196. // if we gave up due to timeout before, don't wait again
  197. if (transmit_previous_timeout) {
  198. if (!(UEINTX & (1<<RWAL))) {
  199. SREG = intr_state;
  200. return;
  201. }
  202. transmit_previous_timeout = 0;
  203. }
  204. // wait for the FIFO to be ready to accept data
  205. timeout = UDFNUML + TRANSMIT_TIMEOUT;
  206. while (1) {
  207. // are we ready to transmit?
  208. if (UEINTX & (1<<RWAL)) break;
  209. SREG = intr_state;
  210. // have we waited too long? This happens if the user
  211. // is not running an application that is listening
  212. if (UDFNUML == timeout) {
  213. transmit_previous_timeout = 1;
  214. return;
  215. }
  216. // has the USB gone offline?
  217. if (!usb_configuration) return;
  218. // get ready to try checking again
  219. intr_state = SREG;
  220. cli();
  221. UENUM = CDC_TX_ENDPOINT;
  222. }
  223. // actually write the byte into the FIFO
  224. UEDATX = c;
  225. // if this completed a packet, transmit it now!
  226. if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
  227. transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
  228. SREG = intr_state;
  229. }
  230. #endif
  231. int usb_serial_class::availableForWrite()
  232. {
  233. uint8_t intr_state, write_size;
  234. if (!usb_configuration) return 0;
  235. intr_state = SREG;
  236. cli();
  237. UENUM = CDC_TX_ENDPOINT;
  238. write_size = CDC_TX_SIZE - UEBCLX;
  239. SREG = intr_state;
  240. return write_size;
  241. }
  242. // transmit a block of data
  243. size_t usb_serial_class::write(const uint8_t *buffer, uint16_t size)
  244. {
  245. uint8_t timeout, intr_state, write_size;
  246. size_t count=0;
  247. // if we're not online (enumerated and configured), error
  248. if (!usb_configuration) {
  249. setWriteError();
  250. goto end;
  251. }
  252. // interrupts are disabled so these functions can be
  253. // used from the main program or interrupt context,
  254. // even both in the same program!
  255. intr_state = SREG;
  256. cli();
  257. UENUM = CDC_TX_ENDPOINT;
  258. // if we gave up due to timeout before, don't wait again
  259. if (transmit_previous_timeout) {
  260. if (!(UEINTX & (1<<RWAL))) {
  261. SREG = intr_state;
  262. setWriteError();
  263. goto end;
  264. }
  265. transmit_previous_timeout = 0;
  266. }
  267. // each iteration of this loop transmits a packet
  268. while (size) {
  269. // wait for the FIFO to be ready to accept data
  270. timeout = UDFNUML + TRANSMIT_TIMEOUT;
  271. while (1) {
  272. // are we ready to transmit?
  273. if (UEINTX & (1<<RWAL)) break;
  274. SREG = intr_state;
  275. // have we waited too long? This happens if the user
  276. // is not running an application that is listening
  277. if (UDFNUML == timeout) {
  278. transmit_previous_timeout = 1;
  279. setWriteError();
  280. goto end;
  281. }
  282. // has the USB gone offline?
  283. if (!usb_configuration) {
  284. setWriteError();
  285. goto end;
  286. }
  287. // get ready to try checking again
  288. intr_state = SREG;
  289. cli();
  290. UENUM = CDC_TX_ENDPOINT;
  291. }
  292. // compute how many bytes will fit into the next packet
  293. write_size = CDC_TX_SIZE - UEBCLX;
  294. if (write_size > size) write_size = size;
  295. size -= write_size;
  296. count += write_size;
  297. #define ASM_COPY1(src, dest, tmp) "ld " tmp ", " src "\n\t" "st " dest ", " tmp "\n\t"
  298. #define ASM_COPY2(src, dest, tmp) ASM_COPY1(src, dest, tmp) ASM_COPY1(src, dest, tmp)
  299. #define ASM_COPY4(src, dest, tmp) ASM_COPY2(src, dest, tmp) ASM_COPY2(src, dest, tmp)
  300. #define ASM_COPY8(src, dest, tmp) ASM_COPY4(src, dest, tmp) ASM_COPY4(src, dest, tmp)
  301. #if 1
  302. // write the packet
  303. do {
  304. uint8_t tmp;
  305. asm volatile(
  306. "L%=begin:" "\n\t"
  307. "ldi r30, %4" "\n\t"
  308. "sub r30, %3" "\n\t"
  309. "cpi r30, %4" "\n\t"
  310. "brsh L%=err" "\n\t"
  311. "lsl r30" "\n\t"
  312. "clr r31" "\n\t"
  313. "subi r30, lo8(-(pm(L%=table)))" "\n\t"
  314. "sbci r31, hi8(-(pm(L%=table)))" "\n\t"
  315. "ijmp" "\n\t"
  316. "L%=err:" "\n\t"
  317. "rjmp L%=end" "\n\t"
  318. "L%=table:" "\n\t"
  319. #if (CDC_TX_SIZE == 64)
  320. ASM_COPY8("Y+", "X", "%1")
  321. ASM_COPY8("Y+", "X", "%1")
  322. ASM_COPY8("Y+", "X", "%1")
  323. ASM_COPY8("Y+", "X", "%1")
  324. #endif
  325. #if (CDC_TX_SIZE >= 32)
  326. ASM_COPY8("Y+", "X", "%1")
  327. ASM_COPY8("Y+", "X", "%1")
  328. #endif
  329. #if (CDC_TX_SIZE >= 16)
  330. ASM_COPY8("Y+", "X", "%1")
  331. #endif
  332. ASM_COPY8("Y+", "X", "%1")
  333. "L%=end:" "\n\t"
  334. : "+y" (buffer), "=r" (tmp)
  335. : "x" (&UEDATX), "r" (write_size), "M" (CDC_TX_SIZE)
  336. : "r30", "r31"
  337. );
  338. } while (0);
  339. #endif
  340. // if this completed a packet, transmit it now!
  341. if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
  342. transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
  343. }
  344. SREG = intr_state;
  345. end:
  346. return count;
  347. }
  348. // transmit a string
  349. /*
  350. void usb_serial_class::write(const char *str)
  351. {
  352. uint16_t size=0;
  353. const char *p=str;
  354. while (*p++) size++;
  355. if (size) write((const uint8_t *)str, size);
  356. }
  357. */
  358. // These are Teensy-specific extensions to the Serial object
  359. // immediately transmit any buffered output.
  360. // This doesn't actually transmit the data - that is impossible!
  361. // USB devices only transmit when the host allows, so the best
  362. // we can do is release the FIFO buffer for when the host wants it
  363. void usb_serial_class::send_now(void)
  364. {
  365. uint8_t intr_state;
  366. intr_state = SREG;
  367. cli();
  368. if (usb_configuration && transmit_flush_timer) {
  369. UENUM = CDC_TX_ENDPOINT;
  370. UEINTX = 0x3A;
  371. transmit_flush_timer = 0;
  372. }
  373. SREG = intr_state;
  374. }
  375. uint32_t usb_serial_class::baud(void)
  376. {
  377. //return *(uint32_t *)cdc_line_coding;
  378. return (uint32_t)cdc_line_coding[0]
  379. | ((uint32_t)cdc_line_coding[1] << 8)
  380. | ((uint32_t)cdc_line_coding[2] << 16)
  381. | ((uint32_t)cdc_line_coding[3] << 24);
  382. }
  383. uint8_t usb_serial_class::stopbits(void)
  384. {
  385. return cdc_line_coding[4];
  386. }
  387. uint8_t usb_serial_class::paritytype(void)
  388. {
  389. return cdc_line_coding[5];
  390. }
  391. uint8_t usb_serial_class::numbits(void)
  392. {
  393. return cdc_line_coding[6];
  394. }
  395. uint8_t usb_serial_class::dtr(void)
  396. {
  397. return (cdc_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0;
  398. }
  399. uint8_t usb_serial_class::rts(void)
  400. {
  401. return (cdc_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0;
  402. }
  403. usb_serial_class::operator bool()
  404. {
  405. if (usb_configuration &&
  406. (cdc_line_rtsdtr & (USB_SERIAL_DTR | USB_SERIAL_RTS))) {
  407. return true;
  408. }
  409. return false;
  410. }
  411. // Preinstantiate Objects //////////////////////////////////////////////////////
  412. usb_serial_class Serial = usb_serial_class();