usbdrvasm128.inc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  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. */
  9. /* Do not link this file! Link usbdrvasm.S instead, which includes the
  10. * appropriate implementation!
  11. */
  12. /*
  13. General Description:
  14. This file is the 12.8 MHz version of the USB driver. It is intended for use
  15. with the internal RC oscillator. Although 12.8 MHz is outside the guaranteed
  16. calibration range of the oscillator, almost all AVRs can reach this frequency.
  17. This version contains a phase locked loop in the receiver routine to cope with
  18. slight clock rate deviations of up to +/- 1%.
  19. See usbdrv.h for a description of the entire driver.
  20. LIMITATIONS
  21. ===========
  22. Although it may seem very handy to save the crystal and use the internal
  23. RC oscillator of the CPU, this method (and this module) has some serious
  24. limitations:
  25. (1) The guaranteed calibration range of the oscillator is only 8.1 MHz.
  26. They typical range is 14.5 MHz and most AVRs can actually reach this rate.
  27. (2) Writing EEPROM and Flash may be unreliable (short data lifetime) since
  28. the write procedure is timed from the RC oscillator.
  29. (3) End Of Packet detection (SE0) should be in bit 1, bit it is only checked
  30. if bits 0 and 1 both read as 0 on D- and D+ read as 0 in the middle. This may
  31. cause problems with old hubs which delay SE0 by up to one cycle.
  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. se0AndStore: ; executed only if both bits 0
  201. st y+, x1 ;[15/17] cycles after start of byte
  202. rjmp se0 ;[17/19]
  203. bit0IsClr:
  204. ifrset phase, USBMINUS ;[04] check phase only if D- changed
  205. lpm ;[05]
  206. in phase, USBIN ;[06] <- phase (one cycle too late)
  207. ori shift, 1 << 0 ;[07]
  208. bit1AfterClr:
  209. andi phase, USBMASK ;[08]
  210. ifioset USBIN, USBMINUS ;[09] <--- sample 1
  211. rjmp bit1IsSet ;[10]
  212. breq se0AndStore ;[11] if D- was 0 in bits 0 AND 1 and D+ was 0 in between, we have SE0
  213. andi shift, ~(7 << 1) ;[12]
  214. in phase, USBIN ;[13] <- phase
  215. breq unstuff1c ;[14]
  216. rjmp bit2AfterClr ;[15]
  217. unstuff1c:
  218. andi fix, ~(1 << 1) ;[16]
  219. nop2 ;[08]
  220. nop2 ;[10]
  221. bit1IsSet:
  222. ifrclr phase, USBMINUS ;[12] check phase only if D- changed
  223. lpm ;[13]
  224. in phase, USBIN ;[14] <- phase (one cycle too late)
  225. ori shift, 1 << 1 ;[15]
  226. nop ;[16]
  227. bit2AfterSet:
  228. ifioclr USBIN, USBMINUS ;[17] <--- sample 2
  229. rjmp bit2IsClr ;[18]
  230. andi shift, ~(7 << 2) ;[19]
  231. breq unstuff2s ;[20]
  232. in phase, USBIN ;[21] <- phase
  233. rjmp bit3AfterSet ;[22]
  234. unstuff2s:
  235. in phase, USBIN ;[22] <- phase (one cycle too late)
  236. andi fix, ~(1 << 2) ;[23]
  237. nop2 ;[16]
  238. nop2 ;[18]
  239. bit2IsClr:
  240. ifrset phase, USBMINUS ;[20] check phase only if D- changed
  241. lpm ;[21]
  242. in phase, USBIN ;[22] <- phase (one cycle too late)
  243. ori shift, 1 << 2 ;[23]
  244. bit3AfterClr:
  245. st y+, data ;[24]
  246. entryAfterClr:
  247. ifioset USBIN, USBMINUS ;[26] <--- sample 3
  248. rjmp bit3IsSet ;[27]
  249. andi shift, ~(7 << 3) ;[28]
  250. breq unstuff3c ;[29]
  251. in phase, USBIN ;[30] <- phase
  252. rjmp bit4AfterClr ;[31]
  253. unstuff3c:
  254. in phase, USBIN ;[31] <- phase (one cycle too late)
  255. andi fix, ~(1 << 3) ;[32]
  256. nop2 ;[25]
  257. nop2 ;[27]
  258. bit3IsSet:
  259. ifrclr phase, USBMINUS ;[29] check phase only if D- changed
  260. lpm ;[30]
  261. in phase, USBIN ;[31] <- phase (one cycle too late)
  262. ori shift, 1 << 3 ;[32]
  263. bit4AfterSet:
  264. mov data, fix ;[33] undo this move by swapping defines
  265. #undef fix
  266. #define fix x1
  267. #undef data
  268. #define data x2
  269. ifioclr USBIN, USBMINUS ;[34] <--- sample 4
  270. rjmp bit4IsClr ;[35]
  271. andi shift, ~(7 << 4) ;[36]
  272. breq unstuff4s ;[37]
  273. in phase, USBIN ;[38] <- phase
  274. rjmp bit5AfterSet ;[39]
  275. unstuff4s:
  276. in phase, USBIN ;[39] <- phase (one cycle too late)
  277. andi fix, ~(1 << 4) ;[40]
  278. nop2 ;[33]
  279. nop2 ;[35]
  280. bit4IsClr:
  281. ifrset phase, USBMINUS ;[37] check phase only if D- changed
  282. lpm ;[38]
  283. in phase, USBIN ;[39] <- phase (one cycle too late)
  284. ori shift, 1 << 4 ;[40]
  285. bit5AfterClr:
  286. ser data ;[41]
  287. ifioset USBIN, USBMINUS ;[42] <--- sample 5
  288. rjmp bit5IsSet ;[43]
  289. andi shift, ~(7 << 5) ;[44]
  290. breq unstuff5c ;[45]
  291. in phase, USBIN ;[46] <- phase
  292. rjmp bit6AfterClr ;[47]
  293. unstuff5c:
  294. in phase, USBIN ;[47] <- phase (one cycle too late)
  295. andi fix, ~(1 << 5) ;[48]
  296. nop2 ;[41]
  297. nop2 ;[43]
  298. bit5IsSet:
  299. ifrclr phase, USBMINUS ;[45] check phase only if D- changed
  300. lpm ;[46]
  301. in phase, USBIN ;[47] <- phase (one cycle too late)
  302. ori shift, 1 << 5 ;[48]
  303. bit6AfterSet:
  304. subi cnt, 1 ;[49]
  305. brcs jumpToOverflow ;[50]
  306. ifioclr USBIN, USBMINUS ;[51] <--- sample 6
  307. rjmp bit6IsClr ;[52]
  308. andi shift, ~(3 << 6) ;[53]
  309. cpi shift, 2 ;[54]
  310. in phase, USBIN ;[55] <- phase
  311. brlt unstuff6s ;[56]
  312. rjmp bit7AfterSet ;[57]
  313. jumpToOverflow:
  314. rjmp overflow
  315. unstuff6s:
  316. andi fix, ~(1 << 6) ;[50]
  317. lpm ;[51]
  318. bit6IsClr:
  319. ifrset phase, USBMINUS ;[54] check phase only if D- changed
  320. lpm ;[55]
  321. in phase, USBIN ;[56] <- phase (one cycle too late)
  322. ori shift, 1 << 6 ;[57]
  323. nop ;[58]
  324. bit7AfterClr:
  325. ifioset USBIN, USBMINUS ;[59] <--- sample 7
  326. rjmp bit7IsSet ;[60]
  327. andi shift, ~(1 << 7) ;[61]
  328. cpi shift, 4 ;[62]
  329. in phase, USBIN ;[63] <- phase
  330. brlt unstuff7c ;[64]
  331. rjmp bit0AfterClr ;[65] -> [00] == [67]
  332. unstuff7c:
  333. andi fix, ~(1 << 7) ;[58]
  334. nop ;[59]
  335. rjmp bit7IsSet ;[60]
  336. bit7IsClr:
  337. ifrset phase, USBMINUS ;[62] check phase only if D- changed
  338. lpm ;[63]
  339. in phase, USBIN ;[64] <- phase (one cycle too late)
  340. ori shift, 1 << 7 ;[65]
  341. nop ;[66]
  342. ;;;;rjmp bit0AfterClr ; -> [00] == [67] moved block up to save jump
  343. bit0AfterClr:
  344. eor fix, shift ;[00]
  345. #undef fix
  346. #define fix x2
  347. #undef data
  348. #define data x1 /* we now have result in data, fix is reset to 0xff */
  349. ifioset USBIN, USBMINUS ;[01] <--- sample 0
  350. rjmp bit0IsSet ;[02]
  351. andi shift, ~(7 << 0) ;[03]
  352. breq unstuff0c ;[04]
  353. in phase, USBIN ;[05] <- phase
  354. rjmp bit1AfterClr ;[06]
  355. unstuff0c:
  356. in phase, USBIN ;[06] <- phase (one cycle too late)
  357. andi fix, ~(1 << 0) ;[07]
  358. ifioclr USBIN, USBMINUS ;[00]
  359. ifioset USBIN, USBPLUS ;[01]
  360. rjmp bit0IsSet ;[02] executed if first expr false or second true
  361. rjmp se0AndStore ;[03] executed only if both bits 0
  362. bit0IsSet:
  363. ifrclr phase, USBMINUS ;[04] check phase only if D- changed
  364. lpm ;[05]
  365. in phase, USBIN ;[06] <- phase (one cycle too late)
  366. ori shift, 1 << 0 ;[07]
  367. bit1AfterSet:
  368. andi shift, ~(7 << 1) ;[08] compensated by "ori shift, 1<<1" if bit1IsClr
  369. ifioclr USBIN, USBMINUS ;[09] <--- sample 1
  370. rjmp bit1IsClr ;[10]
  371. breq unstuff1s ;[11]
  372. nop2 ;[12] do not check for SE0 if bit 0 was 1
  373. in phase, USBIN ;[14] <- phase (one cycle too late)
  374. rjmp bit2AfterSet ;[15]
  375. unstuff1s:
  376. in phase, USBIN ;[13] <- phase
  377. andi fix, ~(1 << 1) ;[14]
  378. lpm ;[07]
  379. nop2 ;[10]
  380. bit1IsClr:
  381. ifrset phase, USBMINUS ;[12] check phase only if D- changed
  382. lpm ;[13]
  383. in phase, USBIN ;[14] <- phase (one cycle too late)
  384. ori shift, 1 << 1 ;[15]
  385. nop ;[16]
  386. bit2AfterClr:
  387. ifioset USBIN, USBMINUS ;[17] <--- sample 2
  388. rjmp bit2IsSet ;[18]
  389. andi shift, ~(7 << 2) ;[19]
  390. breq unstuff2c ;[20]
  391. in phase, USBIN ;[21] <- phase
  392. rjmp bit3AfterClr ;[22]
  393. unstuff2c:
  394. in phase, USBIN ;[22] <- phase (one cycle too late)
  395. andi fix, ~(1 << 2) ;[23]
  396. nop2 ;[16]
  397. nop2 ;[18]
  398. bit2IsSet:
  399. ifrclr phase, USBMINUS ;[20] check phase only if D- changed
  400. lpm ;[21]
  401. in phase, USBIN ;[22] <- phase (one cycle too late)
  402. ori shift, 1 << 2 ;[23]
  403. bit3AfterSet:
  404. st y+, data ;[24]
  405. entryAfterSet:
  406. ifioclr USBIN, USBMINUS ;[26] <--- sample 3
  407. rjmp bit3IsClr ;[27]
  408. andi shift, ~(7 << 3) ;[28]
  409. breq unstuff3s ;[29]
  410. in phase, USBIN ;[30] <- phase
  411. rjmp bit4AfterSet ;[31]
  412. unstuff3s:
  413. in phase, USBIN ;[31] <- phase (one cycle too late)
  414. andi fix, ~(1 << 3) ;[32]
  415. nop2 ;[25]
  416. nop2 ;[27]
  417. bit3IsClr:
  418. ifrset phase, USBMINUS ;[29] check phase only if D- changed
  419. lpm ;[30]
  420. in phase, USBIN ;[31] <- phase (one cycle too late)
  421. ori shift, 1 << 3 ;[32]
  422. bit4AfterClr:
  423. mov data, fix ;[33] undo this move by swapping defines
  424. #undef fix
  425. #define fix x1
  426. #undef data
  427. #define data x2
  428. ifioset USBIN, USBMINUS ;[34] <--- sample 4
  429. rjmp bit4IsSet ;[35]
  430. andi shift, ~(7 << 4) ;[36]
  431. breq unstuff4c ;[37]
  432. in phase, USBIN ;[38] <- phase
  433. rjmp bit5AfterClr ;[39]
  434. unstuff4c:
  435. in phase, USBIN ;[39] <- phase (one cycle too late)
  436. andi fix, ~(1 << 4) ;[40]
  437. nop2 ;[33]
  438. nop2 ;[35]
  439. bit4IsSet:
  440. ifrclr phase, USBMINUS ;[37] check phase only if D- changed
  441. lpm ;[38]
  442. in phase, USBIN ;[39] <- phase (one cycle too late)
  443. ori shift, 1 << 4 ;[40]
  444. bit5AfterSet:
  445. ser data ;[41]
  446. ifioclr USBIN, USBMINUS ;[42] <--- sample 5
  447. rjmp bit5IsClr ;[43]
  448. andi shift, ~(7 << 5) ;[44]
  449. breq unstuff5s ;[45]
  450. in phase, USBIN ;[46] <- phase
  451. rjmp bit6AfterSet ;[47]
  452. unstuff5s:
  453. in phase, USBIN ;[47] <- phase (one cycle too late)
  454. andi fix, ~(1 << 5) ;[48]
  455. nop2 ;[41]
  456. nop2 ;[43]
  457. bit5IsClr:
  458. ifrset phase, USBMINUS ;[45] check phase only if D- changed
  459. lpm ;[46]
  460. in phase, USBIN ;[47] <- phase (one cycle too late)
  461. ori shift, 1 << 5 ;[48]
  462. bit6AfterClr:
  463. subi cnt, 1 ;[49]
  464. brcs overflow ;[50]
  465. ifioset USBIN, USBMINUS ;[51] <--- sample 6
  466. rjmp bit6IsSet ;[52]
  467. andi shift, ~(3 << 6) ;[53]
  468. cpi shift, 2 ;[54]
  469. in phase, USBIN ;[55] <- phase
  470. brlt unstuff6c ;[56]
  471. rjmp bit7AfterClr ;[57]
  472. unstuff6c:
  473. andi fix, ~(1 << 6) ;[50]
  474. lpm ;[51]
  475. bit6IsSet:
  476. ifrclr phase, USBMINUS ;[54] check phase only if D- changed
  477. lpm ;[55]
  478. in phase, USBIN ;[56] <- phase (one cycle too late)
  479. ori shift, 1 << 6 ;[57]
  480. bit7AfterSet:
  481. ifioclr USBIN, USBMINUS ;[59] <--- sample 7
  482. rjmp bit7IsClr ;[60]
  483. andi shift, ~(1 << 7) ;[61]
  484. cpi shift, 4 ;[62]
  485. in phase, USBIN ;[63] <- phase
  486. brlt unstuff7s ;[64]
  487. rjmp bit0AfterSet ;[65] -> [00] == [67]
  488. unstuff7s:
  489. andi fix, ~(1 << 7) ;[58]
  490. nop ;[59]
  491. rjmp bit7IsClr ;[60]
  492. macro POP_STANDARD ; 14 cycles
  493. pop r0
  494. pop cnt
  495. pop x3
  496. pop x2
  497. pop x1
  498. pop shift
  499. pop YH
  500. endm
  501. macro POP_RETI ; 5 cycles
  502. pop YL
  503. out SREG, YL
  504. pop YL
  505. endm
  506. #include "asmcommon.inc"
  507. ;----------------------------------------------------------------------------
  508. ; Transmitting data
  509. ;----------------------------------------------------------------------------
  510. txByteLoop:
  511. txBitloop:
  512. stuffN1Delay: ; [03]
  513. ror shift ;[-5] [11] [63]
  514. brcc doExorN1 ;[-4] [64]
  515. subi x3, 1 ;[-3]
  516. brne commonN1 ;[-2]
  517. lsl shift ;[-1] compensate ror after rjmp stuffDelay
  518. nop ;[00] stuffing consists of just waiting 8 cycles
  519. rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear
  520. sendNakAndReti:
  521. ldi cnt, USBPID_NAK ;[-19]
  522. rjmp sendCntAndReti ;[-18]
  523. sendAckAndReti:
  524. ldi cnt, USBPID_ACK ;[-17]
  525. sendCntAndReti:
  526. mov r0, cnt ;[-16]
  527. ldi YL, 0 ;[-15] R0 address is 0
  528. ldi YH, 0 ;[-14]
  529. ldi cnt, 2 ;[-13]
  530. ; rjmp usbSendAndReti fallthrough
  531. ; USB spec says:
  532. ; idle = J
  533. ; J = (D+ = 0), (D- = 1) or USBOUT = 0x01
  534. ; K = (D+ = 1), (D- = 0) or USBOUT = 0x02
  535. ; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles)
  536. ;usbSend:
  537. ;pointer to data in 'Y'
  538. ;number of bytes in 'cnt' -- including sync byte
  539. ;uses: x1...x3, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x3 = bitstuff cnt]
  540. ;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
  541. usbSendAndReti:
  542. in x2, USBDDR ;[-10] 10 cycles until SOP
  543. ori x2, USBMASK ;[-9]
  544. sbi USBOUT, USBMINUS ;[-8] prepare idle state; D+ and D- must have been 0 (no pullups)
  545. out USBDDR, x2 ;[-6] <--- acquire bus
  546. in x1, USBOUT ;[-5] port mirror for tx loop
  547. ldi shift, 0x40 ;[-4] sync byte is first byte sent (we enter loop after ror)
  548. ldi x2, USBMASK ;[-3]
  549. doExorN1:
  550. eor x1, x2 ;[-2] [06] [62]
  551. ldi x3, 6 ;[-1] [07] [63]
  552. commonN1:
  553. stuffN2Delay:
  554. out USBOUT, x1 ;[00] [08] [64] <--- set bit
  555. ror shift ;[01]
  556. brcc doExorN2 ;[02]
  557. subi x3, 1 ;[03]
  558. brne commonN2 ;[04]
  559. lsl shift ;[05] compensate ror after rjmp stuffDelay
  560. rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear
  561. doExorN2:
  562. eor x1, x2 ;[04] [12]
  563. ldi x3, 6 ;[05] [13]
  564. commonN2:
  565. nop2 ;[06] [14]
  566. subi cnt, 171 ;[08] [16] trick: (3 * 171) & 0xff = 1
  567. out USBOUT, x1 ;[09] [17] <--- set bit
  568. brcs txBitloop ;[10] [27] [44]
  569. stuff6Delay:
  570. ror shift ;[45] [53]
  571. brcc doExor6 ;[46]
  572. subi x3, 1 ;[47]
  573. brne common6 ;[48]
  574. lsl shift ;[49] compensate ror after rjmp stuffDelay
  575. nop ;[50] stuffing consists of just waiting 8 cycles
  576. rjmp stuff6Delay ;[51] after ror, C bit is reliably clear
  577. doExor6:
  578. eor x1, x2 ;[48] [56]
  579. ldi x3, 6 ;[49]
  580. common6:
  581. stuff7Delay:
  582. ror shift ;[50] [58]
  583. out USBOUT, x1 ;[51] <--- set bit
  584. brcc doExor7 ;[52]
  585. subi x3, 1 ;[53]
  586. brne common7 ;[54]
  587. lsl shift ;[55] compensate ror after rjmp stuffDelay
  588. rjmp stuff7Delay ;[56] after ror, C bit is reliably clear
  589. doExor7:
  590. eor x1, x2 ;[54] [62]
  591. ldi x3, 6 ;[55]
  592. common7:
  593. ld shift, y+ ;[56]
  594. nop ;[58]
  595. tst cnt ;[59]
  596. out USBOUT, x1 ;[60] [00]<--- set bit
  597. brne txByteLoop ;[61] [01]
  598. ;make SE0:
  599. cbr x1, USBMASK ;[02] prepare SE0 [spec says EOP may be 15 to 18 cycles]
  600. lds x2, usbNewDeviceAddr;[03]
  601. lsl x2 ;[05] we compare with left shifted address
  602. subi YL, 2 + 0 ;[06] Only assign address on data packets, not ACK/NAK in r0
  603. sbci YH, 0 ;[07]
  604. out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
  605. ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
  606. ;set address only after data packet was sent, not after handshake
  607. breq skipAddrAssign ;[01]
  608. sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer
  609. skipAddrAssign:
  610. ;end of usbDeviceAddress transfer
  611. ldi x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag
  612. USB_STORE_PENDING(x2) ;[04]
  613. ori x1, USBIDLE ;[05]
  614. in x2, USBDDR ;[06]
  615. cbr x2, USBMASK ;[07] set both pins to input
  616. mov x3, x1 ;[08]
  617. cbr x3, USBMASK ;[09] configure no pullup on both pins
  618. lpm ;[10]
  619. lpm ;[13]
  620. out USBOUT, x1 ;[16] <-- out J (idle) -- end of SE0 (EOP signal)
  621. out USBDDR, x2 ;[17] <-- release bus now
  622. out USBOUT, x3 ;[18] <-- ensure no pull-up resistors are active
  623. rjmp doReturn
  624. /*****************************************************************************
  625. The following PHP script generates a code skeleton for the receiver routine:
  626. <?php
  627. function printCmdBuffer($thisBit)
  628. {
  629. global $cycle;
  630. $nextBit = ($thisBit + 1) % 8;
  631. $s = ob_get_contents();
  632. ob_end_clean();
  633. $s = str_replace("#", $thisBit, $s);
  634. $s = str_replace("@", $nextBit, $s);
  635. $lines = explode("\n", $s);
  636. for($i = 0; $i < count($lines); $i++){
  637. $s = $lines[$i];
  638. if(ereg("\\[([0-9-][0-9])\\]", $s, $regs)){
  639. $c = $cycle + (int)$regs[1];
  640. $s = ereg_replace("\\[[0-9-][0-9]\\]", sprintf("[%02d]", $c), $s);
  641. }
  642. if(strlen($s) > 0)
  643. echo "$s\n";
  644. }
  645. }
  646. function printBit($isAfterSet, $bitNum)
  647. {
  648. ob_start();
  649. if($isAfterSet){
  650. ?>
  651. ifioclr USBIN, USBMINUS ;[00] <--- sample
  652. rjmp bit#IsClr ;[01]
  653. andi shift, ~(7 << #) ;[02]
  654. breq unstuff#s ;[03]
  655. in phase, USBIN ;[04] <- phase
  656. rjmp bit@AfterSet ;[05]
  657. unstuff#s:
  658. in phase, USBIN ;[05] <- phase (one cycle too late)
  659. andi fix, ~(1 << #) ;[06]
  660. nop2 ;[-1]
  661. nop2 ;[01]
  662. bit#IsClr:
  663. ifrset phase, USBMINUS ;[03] check phase only if D- changed
  664. lpm ;[04]
  665. in phase, USBIN ;[05] <- phase (one cycle too late)
  666. ori shift, 1 << # ;[06]
  667. <?php
  668. }else{
  669. ?>
  670. ifioset USBIN, USBMINUS ;[00] <--- sample
  671. rjmp bit#IsSet ;[01]
  672. andi shift, ~(7 << #) ;[02]
  673. breq unstuff#c ;[03]
  674. in phase, USBIN ;[04] <- phase
  675. rjmp bit@AfterClr ;[05]
  676. unstuff#c:
  677. in phase, USBIN ;[05] <- phase (one cycle too late)
  678. andi fix, ~(1 << #) ;[06]
  679. nop2 ;[-1]
  680. nop2 ;[01]
  681. bit#IsSet:
  682. ifrclr phase, USBMINUS ;[03] check phase only if D- changed
  683. lpm ;[04]
  684. in phase, USBIN ;[05] <- phase (one cycle too late)
  685. ori shift, 1 << # ;[06]
  686. <?php
  687. }
  688. printCmdBuffer($bitNum);
  689. }
  690. $bitStartCycles = array(1, 9, 17, 26, 34, 42, 51, 59);
  691. for($i = 0; $i < 16; $i++){
  692. $bit = $i % 8;
  693. $emitClrCode = ($i + (int)($i / 8)) % 2;
  694. $cycle = $bitStartCycles[$bit];
  695. if($emitClrCode){
  696. printf("bit%dAfterClr:\n", $bit);
  697. }else{
  698. printf("bit%dAfterSet:\n", $bit);
  699. }
  700. ob_start();
  701. echo " ***** ;[-1]\n";
  702. printCmdBuffer($bit);
  703. printBit(!$emitClrCode, $bit);
  704. if($i == 7)
  705. echo "\n";
  706. }
  707. ?>
  708. *****************************************************************************/