usbdrvasm128.inc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. /* Name: usbdrvasm128.inc
  2. * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
  3. * Author: Christian Starkjohann
  4. * Creation Date: 2008-10-11
  5. * Tabsize: 4
  6. * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
  7. * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
  8. * This Revision: $Id: usbdrvasm128.inc 740 2009-04-13 18:23:31Z cs $
  9. */
  10. /* Do not link this file! Link usbdrvasm.S instead, which includes the
  11. * appropriate implementation!
  12. */
  13. /*
  14. General Description:
  15. This file is the 12.8 MHz version of the USB driver. It is intended for use
  16. with the internal RC oscillator. Although 12.8 MHz is outside the guaranteed
  17. calibration range of the oscillator, almost all AVRs can reach this frequency.
  18. This version contains a phase locked loop in the receiver routine to cope with
  19. slight clock rate deviations of up to +/- 1%.
  20. See usbdrv.h for a description of the entire driver.
  21. LIMITATIONS
  22. ===========
  23. Although it may seem very handy to save the crystal and use the internal
  24. RC oscillator of the CPU, this method (and this module) has some serious
  25. limitations:
  26. (1) The guaranteed calibration range of the oscillator is only 8.1 MHz.
  27. They typical range is 14.5 MHz and most AVRs can actually reach this rate.
  28. (2) Writing EEPROM and Flash may be unreliable (short data lifetime) since
  29. the write procedure is timed from the RC oscillator.
  30. (3) End Of Packet detection is between bit 0 and bit 1 where the EOP condition
  31. may not be reliable when a hub is used. It should be in bit 1.
  32. (4) Code size is much larger than that of the other modules.
  33. Since almost all of this code is timing critical, don't change unless you
  34. really know what you are doing! Many parts require not only a maximum number
  35. of CPU cycles, but even an exact number of cycles!
  36. Implementation notes:
  37. ======================
  38. min frequency: 67 cycles for 8 bit -> 12.5625 MHz
  39. max frequency: 69.286 cycles for 8 bit -> 12.99 MHz
  40. nominal frequency: 12.77 MHz ( = sqrt(min * max))
  41. sampling positions: (next even number in range [+/- 0.5])
  42. cycle index range: 0 ... 66
  43. bits:
  44. .5, 8.875, 17.25, 25.625, 34, 42.375, 50.75, 59.125
  45. [0/1], [9], [17], [25/+26], [34], [+42/43], [51], [59]
  46. bit number: 0 1 2 3 4 5 6 7
  47. spare cycles 1 2 1 2 1 1 1 0
  48. operations to perform: duration cycle
  49. ----------------
  50. eor fix, shift 1 -> 00
  51. andi phase, USBMASK 1 -> 08
  52. breq se0 1 -> 16 (moved to 11)
  53. st y+, data 2 -> 24, 25
  54. mov data, fix 1 -> 33
  55. ser data 1 -> 41
  56. subi cnt, 1 1 -> 49
  57. brcs overflow 1 -> 50
  58. layout of samples and operations:
  59. [##] = sample bit
  60. <##> = sample phase
  61. *##* = operation
  62. 0: *00* [01] 02 03 04 <05> 06 07
  63. 1: *08* [09] 10 11 12 <13> 14 15 *16*
  64. 2: [17] 18 19 20 <21> 22 23
  65. 3: *24* *25* [26] 27 28 29 <30> 31 32
  66. 4: *33* [34] 35 36 37 <38> 39 40
  67. 5: *41* [42] 43 44 45 <46> 47 48
  68. 6: *49* *50* [51] 52 53 54 <55> 56 57 58
  69. 7: [59] 60 61 62 <63> 64 65 66
  70. *****************************************************************************/
  71. /* we prefer positive expressions (do if condition) instead of negative
  72. * (skip if condition), therefore use defines for skip instructions:
  73. */
  74. #define ifioclr sbis
  75. #define ifioset sbic
  76. #define ifrclr sbrs
  77. #define ifrset sbrc
  78. /* The registers "fix" and "data" swap their meaning during the loop. Use
  79. * defines to keep their name constant.
  80. */
  81. #define fix x2
  82. #define data x1
  83. #undef phase /* phase has a default definition to x4 */
  84. #define phase x3
  85. USB_INTR_VECTOR:
  86. ;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt, r0
  87. push YL ;2 push only what is necessary to sync with edge ASAP
  88. in YL, SREG ;1
  89. push YL ;2
  90. ;----------------------------------------------------------------------------
  91. ; Synchronize with sync pattern:
  92. ;----------------------------------------------------------------------------
  93. ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
  94. ;sync up with J to K edge during sync pattern -- use fastest possible loops
  95. ;The first part waits at most 1 bit long since we must be in sync pattern.
  96. ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
  97. ;waitForJ, ensure that this prerequisite is met.
  98. waitForJ:
  99. inc YL
  100. sbis USBIN, USBMINUS
  101. brne waitForJ ; just make sure we have ANY timeout
  102. waitForK:
  103. ;The following code results in a sampling window of 1/4 bit which meets the spec.
  104. sbis USBIN, USBMINUS
  105. rjmp foundK
  106. sbis USBIN, USBMINUS
  107. rjmp foundK
  108. sbis USBIN, USBMINUS
  109. rjmp foundK
  110. sbis USBIN, USBMINUS
  111. rjmp foundK
  112. sbis USBIN, USBMINUS ;[0]
  113. rjmp foundK ;[1]
  114. #if USB_COUNT_SOF
  115. lds YL, usbSofCount
  116. inc YL
  117. sts usbSofCount, YL
  118. #endif /* USB_COUNT_SOF */
  119. #ifdef USB_SOF_HOOK
  120. USB_SOF_HOOK
  121. #endif
  122. rjmp sofError
  123. foundK:
  124. ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling]
  125. ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
  126. ;are cycles from center of first sync (double K) bit after the instruction
  127. push YH ;[2]
  128. lds YL, usbInputBufOffset;[4]
  129. clr YH ;[6]
  130. subi YL, lo8(-(usbRxBuf));[7]
  131. sbci YH, hi8(-(usbRxBuf));[8]
  132. sbis USBIN, USBMINUS ;[9] we want two bits K [we want to sample at 8 + 4 - 1.5 = 10.5]
  133. rjmp haveTwoBitsK ;[10]
  134. pop YH ;[11] undo the push from before
  135. rjmp waitForK ;[13] this was not the end of sync, retry
  136. haveTwoBitsK:
  137. ;----------------------------------------------------------------------------
  138. ; push more registers and initialize values while we sample the first bits:
  139. ;----------------------------------------------------------------------------
  140. #define fix x2
  141. #define data x1
  142. push shift ;[12]
  143. push x1 ;[14]
  144. push x2 ;[16]
  145. ldi shift, 0x80 ;[18] prevent bit-unstuffing but init low bits to 0
  146. ifioset USBIN, USBMINUS ;[19] [01] <--- bit 0 [10.5 + 8 = 18.5]
  147. ori shift, 1<<0 ;[02]
  148. push x3 ;[03]
  149. push cnt ;[05]
  150. push r0 ;[07]
  151. ifioset USBIN, USBMINUS ;[09] <--- bit 1
  152. ori shift, 1<<1 ;[10]
  153. ser fix ;[11]
  154. ldi cnt, USB_BUFSIZE ;[12]
  155. mov data, shift ;[13]
  156. lsl shift ;[14]
  157. nop2 ;[15]
  158. ifioset USBIN, USBMINUS ;[17] <--- bit 2
  159. ori data, 3<<2 ;[18] store in bit 2 AND bit 3
  160. eor shift, data ;[19] do nrzi decoding
  161. andi data, 1<<3 ;[20]
  162. in phase, USBIN ;[21] <- phase
  163. brne jumpToEntryAfterSet ;[22] if USBMINS at bit 3 was 1
  164. nop ;[23]
  165. rjmp entryAfterClr ;[24]
  166. jumpToEntryAfterSet:
  167. rjmp entryAfterSet ;[24]
  168. ;----------------------------------------------------------------------------
  169. ; Receiver loop (numbers in brackets are cycles within byte after instr)
  170. ;----------------------------------------------------------------------------
  171. #undef fix
  172. #define fix x1
  173. #undef data
  174. #define data x2
  175. bit7IsSet:
  176. ifrclr phase, USBMINUS ;[62] check phase only if D- changed
  177. lpm ;[63]
  178. in phase, USBIN ;[64] <- phase (one cycle too late)
  179. ori shift, 1 << 7 ;[65]
  180. nop ;[66]
  181. ;;;;rjmp bit0AfterSet ; -> [00] == [67] moved block up to save jump
  182. bit0AfterSet:
  183. eor fix, shift ;[00]
  184. #undef fix
  185. #define fix x2
  186. #undef data
  187. #define data x1 /* we now have result in data, fix is reset to 0xff */
  188. ifioclr USBIN, USBMINUS ;[01] <--- sample 0
  189. rjmp bit0IsClr ;[02]
  190. andi shift, ~(7 << 0) ;[03]
  191. breq unstuff0s ;[04]
  192. in phase, USBIN ;[05] <- phase
  193. rjmp bit1AfterSet ;[06]
  194. unstuff0s:
  195. in phase, USBIN ;[06] <- phase (one cycle too late)
  196. andi fix, ~(1 << 0) ;[07]
  197. ifioclr USBIN, USBMINUS ;[00]
  198. ifioset USBIN, USBPLUS ;[01]
  199. rjmp bit0IsClr ;[02] executed if first expr false or second true
  200. jumpToSe0AndStore:
  201. rjmp se0AndStore ;[03] executed only if both bits 0
  202. bit0IsClr:
  203. ifrset phase, USBMINUS ;[04] check phase only if D- changed
  204. lpm ;[05]
  205. in phase, USBIN ;[06] <- phase (one cycle too late)
  206. ori shift, 1 << 0 ;[07]
  207. bit1AfterClr:
  208. andi phase, USBMASK ;[08]
  209. ifioset USBIN, USBMINUS ;[09] <--- sample 1
  210. rjmp bit1IsSet ;[10]
  211. breq jumpToSe0AndStore ;[11]
  212. andi shift, ~(7 << 1) ;[12]
  213. in phase, USBIN ;[13] <- phase
  214. breq unstuff1c ;[14]
  215. rjmp bit2AfterClr ;[15]
  216. unstuff1c:
  217. andi fix, ~(1 << 1) ;[16]
  218. nop2 ;[08]
  219. nop2 ;[10]
  220. bit1IsSet:
  221. ifrclr phase, USBMINUS ;[12] check phase only if D- changed
  222. lpm ;[13]
  223. in phase, USBIN ;[14] <- phase (one cycle too late)
  224. ori shift, 1 << 1 ;[15]
  225. nop ;[16]
  226. bit2AfterSet:
  227. ifioclr USBIN, USBMINUS ;[17] <--- sample 2
  228. rjmp bit2IsClr ;[18]
  229. andi shift, ~(7 << 2) ;[19]
  230. breq unstuff2s ;[20]
  231. in phase, USBIN ;[21] <- phase
  232. rjmp bit3AfterSet ;[22]
  233. unstuff2s:
  234. in phase, USBIN ;[22] <- phase (one cycle too late)
  235. andi fix, ~(1 << 2) ;[23]
  236. nop2 ;[16]
  237. nop2 ;[18]
  238. bit2IsClr:
  239. ifrset phase, USBMINUS ;[20] check phase only if D- changed
  240. lpm ;[21]
  241. in phase, USBIN ;[22] <- phase (one cycle too late)
  242. ori shift, 1 << 2 ;[23]
  243. bit3AfterClr:
  244. st y+, data ;[24]
  245. entryAfterClr:
  246. ifioset USBIN, USBMINUS ;[26] <--- sample 3
  247. rjmp bit3IsSet ;[27]
  248. andi shift, ~(7 << 3) ;[28]
  249. breq unstuff3c ;[29]
  250. in phase, USBIN ;[30] <- phase
  251. rjmp bit4AfterClr ;[31]
  252. unstuff3c:
  253. in phase, USBIN ;[31] <- phase (one cycle too late)
  254. andi fix, ~(1 << 3) ;[32]
  255. nop2 ;[25]
  256. nop2 ;[27]
  257. bit3IsSet:
  258. ifrclr phase, USBMINUS ;[29] check phase only if D- changed
  259. lpm ;[30]
  260. in phase, USBIN ;[31] <- phase (one cycle too late)
  261. ori shift, 1 << 3 ;[32]
  262. bit4AfterSet:
  263. mov data, fix ;[33] undo this move by swapping defines
  264. #undef fix
  265. #define fix x1
  266. #undef data
  267. #define data x2
  268. ifioclr USBIN, USBMINUS ;[34] <--- sample 4
  269. rjmp bit4IsClr ;[35]
  270. andi shift, ~(7 << 4) ;[36]
  271. breq unstuff4s ;[37]
  272. in phase, USBIN ;[38] <- phase
  273. rjmp bit5AfterSet ;[39]
  274. unstuff4s:
  275. in phase, USBIN ;[39] <- phase (one cycle too late)
  276. andi fix, ~(1 << 4) ;[40]
  277. nop2 ;[33]
  278. nop2 ;[35]
  279. bit4IsClr:
  280. ifrset phase, USBMINUS ;[37] check phase only if D- changed
  281. lpm ;[38]
  282. in phase, USBIN ;[39] <- phase (one cycle too late)
  283. ori shift, 1 << 4 ;[40]
  284. bit5AfterClr:
  285. ser data ;[41]
  286. ifioset USBIN, USBMINUS ;[42] <--- sample 5
  287. rjmp bit5IsSet ;[43]
  288. andi shift, ~(7 << 5) ;[44]
  289. breq unstuff5c ;[45]
  290. in phase, USBIN ;[46] <- phase
  291. rjmp bit6AfterClr ;[47]
  292. unstuff5c:
  293. in phase, USBIN ;[47] <- phase (one cycle too late)
  294. andi fix, ~(1 << 5) ;[48]
  295. nop2 ;[41]
  296. nop2 ;[43]
  297. bit5IsSet:
  298. ifrclr phase, USBMINUS ;[45] check phase only if D- changed
  299. lpm ;[46]
  300. in phase, USBIN ;[47] <- phase (one cycle too late)
  301. ori shift, 1 << 5 ;[48]
  302. bit6AfterSet:
  303. subi cnt, 1 ;[49]
  304. brcs jumpToOverflow ;[50]
  305. ifioclr USBIN, USBMINUS ;[51] <--- sample 6
  306. rjmp bit6IsClr ;[52]
  307. andi shift, ~(3 << 6) ;[53]
  308. cpi shift, 2 ;[54]
  309. in phase, USBIN ;[55] <- phase
  310. brlt unstuff6s ;[56]
  311. rjmp bit7AfterSet ;[57]
  312. jumpToOverflow:
  313. rjmp overflow
  314. unstuff6s:
  315. andi fix, ~(1 << 6) ;[50]
  316. lpm ;[51]
  317. bit6IsClr:
  318. ifrset phase, USBMINUS ;[54] check phase only if D- changed
  319. lpm ;[55]
  320. in phase, USBIN ;[56] <- phase (one cycle too late)
  321. ori shift, 1 << 6 ;[57]
  322. nop ;[58]
  323. bit7AfterClr:
  324. ifioset USBIN, USBMINUS ;[59] <--- sample 7
  325. rjmp bit7IsSet ;[60]
  326. andi shift, ~(1 << 7) ;[61]
  327. cpi shift, 4 ;[62]
  328. in phase, USBIN ;[63] <- phase
  329. brlt unstuff7c ;[64]
  330. rjmp bit0AfterClr ;[65] -> [00] == [67]
  331. unstuff7c:
  332. andi fix, ~(1 << 7) ;[58]
  333. nop ;[59]
  334. rjmp bit7IsSet ;[60]
  335. se0AndStore:
  336. st y+, x1 ;[15/17] cycles after start of byte
  337. rjmp se0 ;[17/19]
  338. bit7IsClr:
  339. ifrset phase, USBMINUS ;[62] check phase only if D- changed
  340. lpm ;[63]
  341. in phase, USBIN ;[64] <- phase (one cycle too late)
  342. ori shift, 1 << 7 ;[65]
  343. nop ;[66]
  344. ;;;;rjmp bit0AfterClr ; -> [00] == [67] moved block up to save jump
  345. bit0AfterClr:
  346. eor fix, shift ;[00]
  347. #undef fix
  348. #define fix x2
  349. #undef data
  350. #define data x1 /* we now have result in data, fix is reset to 0xff */
  351. ifioset USBIN, USBMINUS ;[01] <--- sample 0
  352. rjmp bit0IsSet ;[02]
  353. andi shift, ~(7 << 0) ;[03]
  354. breq unstuff0c ;[04]
  355. in phase, USBIN ;[05] <- phase
  356. rjmp bit1AfterClr ;[06]
  357. unstuff0c:
  358. in phase, USBIN ;[06] <- phase (one cycle too late)
  359. andi fix, ~(1 << 0) ;[07]
  360. ifioclr USBIN, USBMINUS ;[00]
  361. ifioset USBIN, USBPLUS ;[01]
  362. rjmp bit0IsSet ;[02] executed if first expr false or second true
  363. rjmp se0AndStore ;[03] executed only if both bits 0
  364. bit0IsSet:
  365. ifrclr phase, USBMINUS ;[04] check phase only if D- changed
  366. lpm ;[05]
  367. in phase, USBIN ;[06] <- phase (one cycle too late)
  368. ori shift, 1 << 0 ;[07]
  369. bit1AfterSet:
  370. andi phase, USBMASK ;[08]
  371. ifioclr USBIN, USBMINUS ;[09] <--- sample 1
  372. rjmp bit1IsClr ;[10]
  373. andi shift, ~(7 << 1) ;[11]
  374. breq unstuff1s ;[12]
  375. in phase, USBIN ;[13] <- phase
  376. nop ;[14]
  377. rjmp bit2AfterSet ;[15]
  378. unstuff1s:
  379. in phase, USBIN ;[14] <- phase (one cycle too late)
  380. andi fix, ~(1 << 1) ;[15]
  381. nop2 ;[08]
  382. nop2 ;[10]
  383. bit1IsClr:
  384. ifrset phase, USBMINUS ;[12] check phase only if D- changed
  385. lpm ;[13]
  386. in phase, USBIN ;[14] <- phase (one cycle too late)
  387. breq se0AndStore ;[15] if we come from unstuff1s, Z bit is never set
  388. ori shift, 1 << 1 ;[16]
  389. bit2AfterClr:
  390. ifioset USBIN, USBMINUS ;[17] <--- sample 2
  391. rjmp bit2IsSet ;[18]
  392. andi shift, ~(7 << 2) ;[19]
  393. breq unstuff2c ;[20]
  394. in phase, USBIN ;[21] <- phase
  395. rjmp bit3AfterClr ;[22]
  396. unstuff2c:
  397. in phase, USBIN ;[22] <- phase (one cycle too late)
  398. andi fix, ~(1 << 2) ;[23]
  399. nop2 ;[16]
  400. nop2 ;[18]
  401. bit2IsSet:
  402. ifrclr phase, USBMINUS ;[20] check phase only if D- changed
  403. lpm ;[21]
  404. in phase, USBIN ;[22] <- phase (one cycle too late)
  405. ori shift, 1 << 2 ;[23]
  406. bit3AfterSet:
  407. st y+, data ;[24]
  408. entryAfterSet:
  409. ifioclr USBIN, USBMINUS ;[26] <--- sample 3
  410. rjmp bit3IsClr ;[27]
  411. andi shift, ~(7 << 3) ;[28]
  412. breq unstuff3s ;[29]
  413. in phase, USBIN ;[30] <- phase
  414. rjmp bit4AfterSet ;[31]
  415. unstuff3s:
  416. in phase, USBIN ;[31] <- phase (one cycle too late)
  417. andi fix, ~(1 << 3) ;[32]
  418. nop2 ;[25]
  419. nop2 ;[27]
  420. bit3IsClr:
  421. ifrset phase, USBMINUS ;[29] check phase only if D- changed
  422. lpm ;[30]
  423. in phase, USBIN ;[31] <- phase (one cycle too late)
  424. ori shift, 1 << 3 ;[32]
  425. bit4AfterClr:
  426. mov data, fix ;[33] undo this move by swapping defines
  427. #undef fix
  428. #define fix x1
  429. #undef data
  430. #define data x2
  431. ifioset USBIN, USBMINUS ;[34] <--- sample 4
  432. rjmp bit4IsSet ;[35]
  433. andi shift, ~(7 << 4) ;[36]
  434. breq unstuff4c ;[37]
  435. in phase, USBIN ;[38] <- phase
  436. rjmp bit5AfterClr ;[39]
  437. unstuff4c:
  438. in phase, USBIN ;[39] <- phase (one cycle too late)
  439. andi fix, ~(1 << 4) ;[40]
  440. nop2 ;[33]
  441. nop2 ;[35]
  442. bit4IsSet:
  443. ifrclr phase, USBMINUS ;[37] check phase only if D- changed
  444. lpm ;[38]
  445. in phase, USBIN ;[39] <- phase (one cycle too late)
  446. ori shift, 1 << 4 ;[40]
  447. bit5AfterSet:
  448. ser data ;[41]
  449. ifioclr USBIN, USBMINUS ;[42] <--- sample 5
  450. rjmp bit5IsClr ;[43]
  451. andi shift, ~(7 << 5) ;[44]
  452. breq unstuff5s ;[45]
  453. in phase, USBIN ;[46] <- phase
  454. rjmp bit6AfterSet ;[47]
  455. unstuff5s:
  456. in phase, USBIN ;[47] <- phase (one cycle too late)
  457. andi fix, ~(1 << 5) ;[48]
  458. nop2 ;[41]
  459. nop2 ;[43]
  460. bit5IsClr:
  461. ifrset phase, USBMINUS ;[45] check phase only if D- changed
  462. lpm ;[46]
  463. in phase, USBIN ;[47] <- phase (one cycle too late)
  464. ori shift, 1 << 5 ;[48]
  465. bit6AfterClr:
  466. subi cnt, 1 ;[49]
  467. brcs overflow ;[50]
  468. ifioset USBIN, USBMINUS ;[51] <--- sample 6
  469. rjmp bit6IsSet ;[52]
  470. andi shift, ~(3 << 6) ;[53]
  471. cpi shift, 2 ;[54]
  472. in phase, USBIN ;[55] <- phase
  473. brlt unstuff6c ;[56]
  474. rjmp bit7AfterClr ;[57]
  475. unstuff6c:
  476. andi fix, ~(1 << 6) ;[50]
  477. lpm ;[51]
  478. bit6IsSet:
  479. ifrclr phase, USBMINUS ;[54] check phase only if D- changed
  480. lpm ;[55]
  481. in phase, USBIN ;[56] <- phase (one cycle too late)
  482. ori shift, 1 << 6 ;[57]
  483. bit7AfterSet:
  484. ifioclr USBIN, USBMINUS ;[59] <--- sample 7
  485. rjmp bit7IsClr ;[60]
  486. andi shift, ~(1 << 7) ;[61]
  487. cpi shift, 4 ;[62]
  488. in phase, USBIN ;[63] <- phase
  489. brlt unstuff7s ;[64]
  490. rjmp bit0AfterSet ;[65] -> [00] == [67]
  491. unstuff7s:
  492. andi fix, ~(1 << 7) ;[58]
  493. nop ;[59]
  494. rjmp bit7IsClr ;[60]
  495. macro POP_STANDARD ; 14 cycles
  496. pop r0
  497. pop cnt
  498. pop x3
  499. pop x2
  500. pop x1
  501. pop shift
  502. pop YH
  503. endm
  504. macro POP_RETI ; 5 cycles
  505. pop YL
  506. out SREG, YL
  507. pop YL
  508. endm
  509. #include "asmcommon.inc"
  510. ;----------------------------------------------------------------------------
  511. ; Transmitting data
  512. ;----------------------------------------------------------------------------
  513. txByteLoop:
  514. txBitloop:
  515. stuffN1Delay: ; [03]
  516. ror shift ;[-5] [11] [63]
  517. brcc doExorN1 ;[-4] [64]
  518. subi x3, 1 ;[-3]
  519. brne commonN1 ;[-2]
  520. lsl shift ;[-1] compensate ror after rjmp stuffDelay
  521. nop ;[00] stuffing consists of just waiting 8 cycles
  522. rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear
  523. sendNakAndReti:
  524. ldi cnt, USBPID_NAK ;[-19]
  525. rjmp sendCntAndReti ;[-18]
  526. sendAckAndReti:
  527. ldi cnt, USBPID_ACK ;[-17]
  528. sendCntAndReti:
  529. mov r0, cnt ;[-16]
  530. ldi YL, 0 ;[-15] R0 address is 0
  531. ldi YH, 0 ;[-14]
  532. ldi cnt, 2 ;[-13]
  533. ; rjmp usbSendAndReti fallthrough
  534. ; USB spec says:
  535. ; idle = J
  536. ; J = (D+ = 0), (D- = 1) or USBOUT = 0x01
  537. ; K = (D+ = 1), (D- = 0) or USBOUT = 0x02
  538. ; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles)
  539. ;usbSend:
  540. ;pointer to data in 'Y'
  541. ;number of bytes in 'cnt' -- including sync byte
  542. ;uses: x1...x3, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x3 = bitstuff cnt]
  543. ;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
  544. usbSendAndReti:
  545. in x2, USBDDR ;[-10] 10 cycles until SOP
  546. ori x2, USBMASK ;[-9]
  547. sbi USBOUT, USBMINUS ;[-8] prepare idle state; D+ and D- must have been 0 (no pullups)
  548. out USBDDR, x2 ;[-6] <--- acquire bus
  549. in x1, USBOUT ;[-5] port mirror for tx loop
  550. ldi shift, 0x40 ;[-4] sync byte is first byte sent (we enter loop after ror)
  551. ldi x2, USBMASK ;[-3]
  552. doExorN1:
  553. eor x1, x2 ;[-2] [06] [62]
  554. ldi x3, 6 ;[-1] [07] [63]
  555. commonN1:
  556. stuffN2Delay:
  557. out USBOUT, x1 ;[00] [08] [64] <--- set bit
  558. ror shift ;[01]
  559. brcc doExorN2 ;[02]
  560. subi x3, 1 ;[03]
  561. brne commonN2 ;[04]
  562. lsl shift ;[05] compensate ror after rjmp stuffDelay
  563. rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear
  564. doExorN2:
  565. eor x1, x2 ;[04] [12]
  566. ldi x3, 6 ;[05] [13]
  567. commonN2:
  568. nop2 ;[06] [14]
  569. subi cnt, 171 ;[08] [16] trick: (3 * 171) & 0xff = 1
  570. out USBOUT, x1 ;[09] [17] <--- set bit
  571. brcs txBitloop ;[10] [27] [44]
  572. stuff6Delay:
  573. ror shift ;[45] [53]
  574. brcc doExor6 ;[46]
  575. subi x3, 1 ;[47]
  576. brne common6 ;[48]
  577. lsl shift ;[49] compensate ror after rjmp stuffDelay
  578. nop ;[50] stuffing consists of just waiting 8 cycles
  579. rjmp stuff6Delay ;[51] after ror, C bit is reliably clear
  580. doExor6:
  581. eor x1, x2 ;[48] [56]
  582. ldi x3, 6 ;[49]
  583. common6:
  584. stuff7Delay:
  585. ror shift ;[50] [58]
  586. out USBOUT, x1 ;[51] <--- set bit
  587. brcc doExor7 ;[52]
  588. subi x3, 1 ;[53]
  589. brne common7 ;[54]
  590. lsl shift ;[55] compensate ror after rjmp stuffDelay
  591. rjmp stuff7Delay ;[56] after ror, C bit is reliably clear
  592. doExor7:
  593. eor x1, x2 ;[54] [62]
  594. ldi x3, 6 ;[55]
  595. common7:
  596. ld shift, y+ ;[56]
  597. nop ;[58]
  598. tst cnt ;[59]
  599. out USBOUT, x1 ;[60] [00]<--- set bit
  600. brne txByteLoop ;[61] [01]
  601. ;make SE0:
  602. cbr x1, USBMASK ;[02] prepare SE0 [spec says EOP may be 15 to 18 cycles]
  603. lds x2, usbNewDeviceAddr;[03]
  604. lsl x2 ;[05] we compare with left shifted address
  605. subi YL, 2 + 0 ;[06] Only assign address on data packets, not ACK/NAK in r0
  606. sbci YH, 0 ;[07]
  607. out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
  608. ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
  609. ;set address only after data packet was sent, not after handshake
  610. breq skipAddrAssign ;[01]
  611. sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer
  612. skipAddrAssign:
  613. ;end of usbDeviceAddress transfer
  614. ldi x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag
  615. USB_STORE_PENDING(x2) ;[04]
  616. ori x1, USBIDLE ;[05]
  617. in x2, USBDDR ;[06]
  618. cbr x2, USBMASK ;[07] set both pins to input
  619. mov x3, x1 ;[08]
  620. cbr x3, USBMASK ;[09] configure no pullup on both pins
  621. lpm ;[10]
  622. lpm ;[13]
  623. out USBOUT, x1 ;[16] <-- out J (idle) -- end of SE0 (EOP signal)
  624. out USBDDR, x2 ;[17] <-- release bus now
  625. out USBOUT, x3 ;[18] <-- ensure no pull-up resistors are active
  626. rjmp doReturn
  627. /*****************************************************************************
  628. The following PHP script generates a code skeleton for the receiver routine:
  629. <?php
  630. function printCmdBuffer($thisBit)
  631. {
  632. global $cycle;
  633. $nextBit = ($thisBit + 1) % 8;
  634. $s = ob_get_contents();
  635. ob_end_clean();
  636. $s = str_replace("#", $thisBit, $s);
  637. $s = str_replace("@", $nextBit, $s);
  638. $lines = explode("\n", $s);
  639. for($i = 0; $i < count($lines); $i++){
  640. $s = $lines[$i];
  641. if(ereg("\\[([0-9-][0-9])\\]", $s, $regs)){
  642. $c = $cycle + (int)$regs[1];
  643. $s = ereg_replace("\\[[0-9-][0-9]\\]", sprintf("[%02d]", $c), $s);
  644. }
  645. if(strlen($s) > 0)
  646. echo "$s\n";
  647. }
  648. }
  649. function printBit($isAfterSet, $bitNum)
  650. {
  651. ob_start();
  652. if($isAfterSet){
  653. ?>
  654. ifioclr USBIN, USBMINUS ;[00] <--- sample
  655. rjmp bit#IsClr ;[01]
  656. andi shift, ~(7 << #) ;[02]
  657. breq unstuff#s ;[03]
  658. in phase, USBIN ;[04] <- phase
  659. rjmp bit@AfterSet ;[05]
  660. unstuff#s:
  661. in phase, USBIN ;[05] <- phase (one cycle too late)
  662. andi fix, ~(1 << #) ;[06]
  663. nop2 ;[-1]
  664. nop2 ;[01]
  665. bit#IsClr:
  666. ifrset phase, USBMINUS ;[03] check phase only if D- changed
  667. lpm ;[04]
  668. in phase, USBIN ;[05] <- phase (one cycle too late)
  669. ori shift, 1 << # ;[06]
  670. <?php
  671. }else{
  672. ?>
  673. ifioset USBIN, USBMINUS ;[00] <--- sample
  674. rjmp bit#IsSet ;[01]
  675. andi shift, ~(7 << #) ;[02]
  676. breq unstuff#c ;[03]
  677. in phase, USBIN ;[04] <- phase
  678. rjmp bit@AfterClr ;[05]
  679. unstuff#c:
  680. in phase, USBIN ;[05] <- phase (one cycle too late)
  681. andi fix, ~(1 << #) ;[06]
  682. nop2 ;[-1]
  683. nop2 ;[01]
  684. bit#IsSet:
  685. ifrclr phase, USBMINUS ;[03] check phase only if D- changed
  686. lpm ;[04]
  687. in phase, USBIN ;[05] <- phase (one cycle too late)
  688. ori shift, 1 << # ;[06]
  689. <?php
  690. }
  691. printCmdBuffer($bitNum);
  692. }
  693. $bitStartCycles = array(1, 9, 17, 26, 34, 42, 51, 59);
  694. for($i = 0; $i < 16; $i++){
  695. $bit = $i % 8;
  696. $emitClrCode = ($i + (int)($i / 8)) % 2;
  697. $cycle = $bitStartCycles[$bit];
  698. if($emitClrCode){
  699. printf("bit%dAfterClr:\n", $bit);
  700. }else{
  701. printf("bit%dAfterSet:\n", $bit);
  702. }
  703. ob_start();
  704. echo " ***** ;[-1]\n";
  705. printCmdBuffer($bit);
  706. printBit(!$emitClrCode, $bit);
  707. if($i == 7)
  708. echo "\n";
  709. }
  710. ?>
  711. *****************************************************************************/