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.

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