Sie sind hier

Source Code des DDS-Experiments

Im folgeden ist der gesamte Quellcode des DDS-Experimentes dargestellt. Um für eine Softwarelösung doch zu einer brauchbaren Performance zu gelangen, wurde der DDS-Algorithmus incl. der Steuerung (Drehgeber, Display) in Assembler realisiert.

Folgende Komponenten wurden zusätzlich noch verwendet:
  • ZN428: Der Digital-Analogwandler (DAC). Seine 8 Datenleitungen (Bit 8 .. Bit 1) wurden mit dem Port B (PB0 .. PB7) verbunden. Also Bit 8 des DAC entspricht Bit 0 von Port B. Der /ENABLE-Eingang liegt an Port D3.
  • SLR2016: ein vierstelliges 7-Segment-display von Osram/Infineon. Es hat einen 7 bit breiten Datenbus D0 .. D6 der mit dem Port B (PB0 .. PB6) verbunden ist. Des weiteren hat das Display zwei Adressleitungen A0 und A1, die ensprechend mit Port D0 und D1 verbunden sind. Das /WR-Signal der Anzeige liegt schließlich auf Port D2.
  • Der Drehgeber: Es handelt sich um einen handelsüblichen Drehgeber mit drei Anschlüsse für den Drehgeberteil sowie zwei weiteren für die Taster-Funktion (hier aber nicht verwendet). Der gmeinsame Anschluß liegt auf Masse; die beiden Signalleitungen liegen an den Ports PD4 und PD5.

  1. .nolist
  2. .include "tn2313def.inc"
  3. .list
  4.  
  5. .def da_out = r1 ; buffer for the byte to be written to DAC
  6.  
  7. .def X0 = R2 ; X-register (5 byte, 40 bit)
  8. .def X1 = R3
  9. .def X2 = R4
  10. .def X3 = R5
  11. .def X4 = R6
  12.  
  13. .def Y0 = R7 ; Y-register (4 byte, 32 bit)
  14. .def Y1 = R8
  15. .def Y2 = R9
  16. .def Y3 = R10
  17.  
  18. .def Z0 = R11 ; Z-register (5 byte; 32 bit)
  19. .def Z1 = R12
  20. .def Z2 = R13
  21. .def Z3 = R14
  22. .def Z4 = R15
  23.  
  24. .def A = r16 ; something like THE accu - not the phase accumulator!
  25. .def zero = r17 ; a register being filled with 0
  26. .def kbd_stat = r18 ; the status of the rotary encoder
  27. .def digit_adm = r19 ; the next digit getting data
  28.  
  29. .def tw_0 = r20 ; the tuning word
  30. .def tw_1 = r21
  31.  
  32. .def pa_0 = r22 ; the pase accumulator
  33. .def pa_1 = r23
  34.  
  35. .def wz_a1 = r24
  36.  
  37. .equ CNT = 100
  38. .equ F_STEP = 20
  39.  
  40. .cseg
  41. ; the jump table for all the interrupts
  42. rjmp main
  43. rjmp main
  44. rjmp main
  45. rjmp main
  46. rjmp main
  47. rjmp main
  48. rjmp main
  49. rjmp main
  50. rjmp main
  51. rjmp main
  52. rjmp main
  53. rjmp main
  54. rjmp main
  55. rjmp irq_service
  56. rjmp main
  57. rjmp main
  58. rjmp main
  59. rjmp main
  60. rjmp main
  61.  
  62. irq_service:
  63. ; the irq service routine
  64. ; save some registers on the stack
  65. push A
  66. in A,SREG
  67. push A
  68. push ZL
  69. push ZH
  70.  
  71. ; write the data byte to the bus and hence to the DAC
  72. out PORTB,da_out
  73.  
  74. ; sync with timer - an algorithm to avoid phase jitter coming fron
  75. ; interrupts on one, two or three cycle operations
  76. in A,TCNT0
  77. subi A,0x0f
  78.  
  79. ldi ZH,high(delay)
  80. ldi ZL,low(delay)
  81.  
  82. add ZL,A
  83. adc ZH,zero
  84.  
  85. ijmp
  86. delay:
  87. nop
  88. nop
  89. nop
  90. nop
  91. nop
  92. nop
  93.  
  94. ; now trigger the DAC - the value on the bus is valid
  95. ; /ENABLE of ZN478 goes low (active)
  96. cbi PORTD,3
  97.  
  98. ; determine next value: add tuning word to phase accumulator
  99. ; ignore carry
  100. add pa_0,tw_0
  101. adc pa_1,tw_1
  102.  
  103. ; the phase accumulator is like a saw tooth signal.
  104. ; convert is to a sine by using a sin-table
  105. ldi ZH,high(SIN_TABLE<<1)
  106. ldi ZL,low(SIN_TABLE<<1)
  107.  
  108. add ZL,pa_1
  109. adc ZH,zero
  110.  
  111. lpm A,Z
  112. ; store the value in da_out - we use it in the next interrupt
  113. mov da_out,A
  114.  
  115. ; now the /ENABLE pulse for the DAC was long enough
  116. ; /ENABLE of ZN478 goes high (inactive)
  117. sbi PORTD,3
  118.  
  119. ; now the display - 4 digits will be managed. In each IRQ
  120. ; another one will be processed
  121. ; something to do?
  122. sbrc digit_adm,7
  123. ; if the MSB is set, the data for display are not yet ready - try
  124. ; in next interrupt ...
  125. rjmp irq_exit
  126.  
  127. ; this ends up in a computed goto - depending on the digit
  128. ; to be processed
  129. mov A,digit_adm
  130. lsl A
  131. lsl A
  132. add A,digit_adm
  133.  
  134. ldi ZH,high(computed_goto)
  135. ldi ZL,low(computed_goto)
  136.  
  137. add ZL,A
  138. adc ZH,zero
  139.  
  140. ; this is the computed goto based on ZH/ZL content
  141. ijmp
  142.  
  143. computed_goto:
  144. do_nothing:
  145. ; we are done - nothing to do
  146. rjmp irq_exit
  147. nop
  148. nop
  149. nop
  150. nop
  151.  
  152. do_digit_0:
  153. ; set the address for digit0
  154. cbi PORTD,0
  155. cbi PORTD,1
  156. ; load the value of the digit from SRAM
  157. lds A,digit0
  158. rjmp digit_exit
  159.  
  160. do_digit_1:
  161. sbi PORTD,0
  162. cbi PORTD,1
  163. lds A,digit1
  164. rjmp digit_exit
  165.  
  166. do_digit_2:
  167. cbi PORTD,0
  168. sbi PORTD,1
  169. lds A,digit2
  170. rjmp digit_exit
  171.  
  172. do_digit_3:
  173. sbi PORTD,0
  174. sbi PORTD,1
  175. lds A,digit3
  176.  
  177. digit_exit:
  178. ; send the byte out to the data bus PORTB
  179. out PORTB,A
  180. ; set /WR of the display to low (active)
  181. cbi PORTD,2
  182. ; advance to the 'next' digit which is the previous one
  183. ; the cycle over all digits is over if 0xff. Then no further
  184. ; display update will happen until tuning word has changed
  185. dec digit_adm
  186.  
  187. irq_exit:
  188. ; restore some register
  189. pop ZH
  190. pop ZL
  191. pop A
  192. out SREG,A
  193. pop A
  194.  
  195. ; the write-pulse was long enough
  196. ; set /WR of the display to high (inactive)
  197. sbi PORTD,2
  198.  
  199. ; end of interrupt
  200. reti
  201.  
  202.  
  203. main:
  204. ; initialization
  205. ; fill the zero-register with zero
  206. ldi zero,0
  207.  
  208. ; set stack pointer to top of memory
  209. ldi A,0xdf
  210. out SPL,A
  211.  
  212. ; initialize port B
  213. ; PB0-PB7: data bus, no pullup
  214. ; this is the data bus for the DAC and for the display
  215. ; we always send data out - we never read from that bus
  216. ldi A,0b11111111
  217. out DDRB,A
  218.  
  219. ; initialize port D
  220. ; out PD0-PD1: A0-A1, digit select A0 and A1 for display
  221. ; out PD2: WR\ for display
  222. ; out PD3: ENABLE\ for DAC
  223. ; in PD4: Phase1 with pull-up - one pin of the rotary encoder
  224. ; in PD5: Phase2 with pull-up - the other pin of the rotary encoder
  225. ; in PD6: Pushbutton with pull-ap - the switch function (press, push)
  226. ; of the rotary encoder
  227. ; in PD7: not available - not used
  228. ldi A,0b01001111
  229. out DDRD,A
  230. ; set /WR and /ENABLE to inactive (high) and
  231. ; set the pull-up resisors for the inputs of the rotary encoder to high
  232. ldi A,0b00111100
  233. out PORTD,A
  234.  
  235. ; set tuning word to 1 kHz (328)
  236. ldi A,0x48
  237. mov tw_0,A
  238. ldi A,0x01
  239. mov tw_1,A
  240.  
  241. ; clear the pase accumulator - not really necessary
  242. mov pa_0,zero
  243. mov pa_1,zero
  244.  
  245. ; display to status 0x80
  246. ldi A,0x80
  247. mov digit_adm,A
  248.  
  249. main_50:
  250. rcall update_display
  251. sbrc digit_adm,7
  252. rjmp main_50
  253.  
  254. ; set an initial value for the DAC
  255. ldi A,0x80
  256. mov da_out,A
  257.  
  258. ; initialize timer 0
  259. ; no usage of any port
  260. ; CTC-mode
  261. ; no prescaler
  262. ldi A,0b00000010
  263. out TCCR0A,A
  264.  
  265. ldi A,0b00000001
  266. out TCCR0B,A
  267.  
  268. ; Counter register (100-1)
  269. ldi A,CNT-1
  270. out OCR0A,A
  271.  
  272. ; interrupt on compare match
  273. ldi A,0b0000001
  274. out TIMSK,A
  275.  
  276. ; poll keys for the first time
  277. in kbd_stat,PIND
  278. lsr kbd_stat
  279. lsr kbd_stat
  280. andi kbd_stat,0b00001100
  281.  
  282. ; interrupt enable
  283. sei
  284.  
  285. loop:
  286. ; poll rotary encoder
  287. ; determine direction (left, right) by use of a
  288. ; state engine
  289. ldi ZH,high(kbd_state_engine<<1)
  290. ldi ZL,low(kbd_state_engine<<1)
  291.  
  292. mov A,kbd_stat
  293. andi A,0x3c
  294. add ZL,A
  295. adc ZH,zero
  296.  
  297. in A,PIND
  298. andi A,0x30
  299. swap A
  300.  
  301. add ZL,A
  302. adc ZH,zero
  303.  
  304. lpm kbd_stat,Z
  305.  
  306. sbrc kbd_stat,0
  307. ; a step in CCW direction was detected. Decrement
  308. ; the tuning word
  309. rjmp cmd_dn
  310.  
  311. sbrc kbd_stat,1
  312. ; a step in CW direction was detected. Increment
  313. ; the tuning word
  314. rjmp cmd_up
  315.  
  316. cpi kbd_stat,0x3c
  317. breq kbd_stat_error
  318.  
  319. ; nothing interesting happened - so we try to update the
  320. ; display but maybe even there is nothing to do ...
  321. rcall update_display
  322.  
  323. rjmp loop
  324.  
  325. cmd_up:
  326. ; incrementing tuning word
  327. ldi A,F_STEP
  328.  
  329. add tw_0,A
  330. adc tw_1,zero
  331. andi kbd_stat,0xfc
  332.  
  333. ; this causes a recalculation of the frequency and thus updating
  334. ; the display
  335. ldi A,0x80
  336. mov digit_adm,A
  337.  
  338. rjmp loop
  339.  
  340. cmd_dn:
  341. ; decrementing tuning word
  342. ldi A,F_STEP
  343.  
  344. sub tw_0,A
  345. sbc tw_1,zero
  346. andi kbd_stat,0xfc
  347.  
  348. ; this causes a recalculation of the frequency and thus updating
  349. ; the display
  350. ldi A,0x80
  351. mov digit_adm,A
  352.  
  353. rjmp loop
  354.  
  355. kbd_stat_error:
  356. ; some unexpected state in the state machine of the rotary encoder
  357. ; entered. Initialize the whole stuff ...
  358. sbi PORTD,6
  359. in kbd_stat,PIND
  360. lsr kbd_stat
  361. lsr kbd_stat
  362. andi kbd_stat,0b00001100
  363. cbi PORTD,6
  364. rjmp loop
  365.  
  366. update_display:
  367. ; here, the digits of the display will be calculated
  368. ; this step consists of multiple phases which are
  369. ; distributed over multiple cycles of the main loop
  370. ; if bit 7 of digit_adm is set, we do not do anything
  371. sbrs digit_adm,7
  372. ret
  373.  
  374. ; each phase corresponds to one computed goto
  375. ldi ZH,high(jump_table)
  376. ldi ZL,low(jump_table)
  377.  
  378. mov A,digit_adm
  379. andi A,0x07
  380.  
  381. clc
  382. adc ZL,A
  383. adc ZH,zero
  384.  
  385. ; the computed goto
  386. ijmp
  387.  
  388. jump_table:
  389. rjmp update_display_prepare
  390. rjmp update_display_d0
  391. rjmp update_display_d1
  392. rjmp update_display_d2
  393. rjmp update_display_d3
  394. rjmp update_display_d4
  395. rjmp update_display_final
  396. ret
  397.  
  398. update_display_prepare:
  399. ; do some calculations
  400. ; f_out = ((F_CPU div 256) * tw) div (CNT * 256)
  401.  
  402. ; 1. F_CPU (20 MHz) div 256 -> X (=0x01312c)
  403. clr X4
  404. clr X3
  405. ldi A,0x01
  406. mov X2,A
  407. ldi A,0x31
  408. mov X1,A
  409. ldi A,0x2d
  410. mov X0,A
  411.  
  412. ; 2. tw -> Y
  413. mov Y0,tw_0
  414. mov Y1,tw_1
  415. clr Y2
  416. clr Y3
  417.  
  418. rcall multiply_24_by_16
  419.  
  420. ; 3. Z->X
  421. mov X0,Z0
  422. mov X1,Z1
  423. mov X2,Z2
  424. mov X3,Z3
  425. mov X4,Z4
  426.  
  427. ; 4. CNT -> Y
  428. ldi A,CNT
  429. mov Y0,A
  430. clr Y1
  431.  
  432. rcall divide_40_by_16
  433.  
  434. ; rounding
  435. sbrs Z0,7
  436. rjmp udp_90
  437.  
  438. ldi A,1
  439. adc Z1,A
  440. adc Z2,zero
  441. adc Z3,zero
  442. adc Z4,zero
  443.  
  444. udp_90:
  445. mov X1,Z2
  446. mov X0,Z1
  447.  
  448. inc digit_adm
  449. ; now we have calculated the output frequency in Hz based on
  450. ; CPU-clock frequency, tuning word and divider factor of
  451. ; the counter (CNT)
  452. ; note: the frequency must be somewhere between 0 and 99999 Hz.
  453. ; of course, already above a few kHz, the output signal is far away
  454. ; from a sine;
  455. ret
  456.  
  457. update_display_d0:
  458. ; determine the 1 Hz digit
  459. rcall divide_by_ten
  460. mov A,X0
  461. ori A,0x30
  462. sts digit0,A
  463. inc digit_adm
  464. ret
  465.  
  466. update_display_d1:
  467. ; determine the 10 Hz digit
  468. mov X0,Z0
  469. mov X1,Z1
  470. rcall divide_by_ten
  471. mov A,X0
  472. ori A,0x30
  473. sts digit1,A
  474. inc digit_adm
  475. ret
  476.  
  477. update_display_d2:
  478. ; determine the 100 Hz digit
  479. mov X0,Z0
  480. mov X1,Z1
  481. rcall divide_by_ten
  482. mov A,X0
  483. ori A,0x30
  484. sts digit2,A
  485. inc digit_adm
  486. ret
  487.  
  488. update_display_d3:
  489. ; determine the 1 kHz digit
  490. mov X0,Z0
  491. mov X1,Z1
  492. rcall divide_by_ten
  493. mov A,X0
  494. ori A,0x30
  495. sts digit3,A
  496. inc digit_adm
  497. ret
  498.  
  499. update_display_d4:
  500. ; determine the 10 kHz digit
  501. mov X0,Z0
  502. mov X1,Z1
  503. rcall divide_by_ten
  504. mov A,X0
  505. ori A,0x30
  506. sts digit4,A
  507. inc digit_adm
  508. ret
  509.  
  510. update_display_final:
  511. ; we can display only 4 digits. Above 10 kHz, we simply skip the 1 Hz
  512. ; digit. digit 1 to 4 will be moved to digit 0 to 3.
  513. lds A,digit4
  514. cpi A,0x30
  515. breq udf_90
  516.  
  517. lds A,digit1
  518. sts digit0,A
  519.  
  520. lds A,digit2
  521. sts digit1,A
  522.  
  523. lds A,digit3
  524. sts digit2,A
  525.  
  526. lds A,digit4
  527. sts digit3,A
  528.  
  529. udf_90:
  530. ; all digits are calculted; they are ready for being displayed
  531. ldi digit_adm,0x04
  532. ret
  533.  
  534. ; now some arithmetic routines
  535. divide_by_ten:
  536. clr Y1
  537. ldi A,0x0a
  538. mov Y0,A
  539.  
  540. clr Z0
  541. clr Z1
  542.  
  543. rcall normalize
  544.  
  545. dbt_10:
  546. rcall test_subtract
  547.  
  548. rol Z0
  549. rol Z1
  550.  
  551. sbrc Z0,0
  552. rcall subtract
  553.  
  554. dec wz_a1
  555. brne dbt_20
  556. ret
  557.  
  558. dbt_20:
  559. lsr Y1
  560. ror Y0
  561. rjmp dbt_10
  562.  
  563. divide_40_by_16:
  564. ; clear Z-register
  565. clr Z0
  566. clr Z1
  567. clr Z2
  568. clr Z3
  569. clr Z4
  570.  
  571. ; shift X, Y commonly to left
  572. div_01:
  573. sbrc X4,7
  574. rjmp div_02
  575. sbrc X4,6
  576. rjmp div_02
  577. sbrc Y1,7
  578. rjmp div_02
  579. sbrc Y1,6
  580. rjmp div_02
  581.  
  582. lsl X0
  583. rol X1
  584. rol X2
  585. rol X3
  586. rol X4
  587.  
  588. lsl Y0
  589. rol Y1
  590.  
  591. rjmp div_01
  592.  
  593. div_02:
  594. ldi wz_a1,25
  595.  
  596. div_03:
  597. sbrc Y1,7
  598. rjmp div_10
  599. sbrc Y1,6
  600. rjmp div_10
  601. lsl Y0
  602. rol Y1
  603. inc wz_a1
  604. rjmp div_03
  605.  
  606. div_10:
  607. clc
  608. cpc X3,Y0
  609. cpc X4,Y1
  610. brcc div_12
  611. clc
  612. rjmp div_13
  613. div_12:
  614. sbc X3,Y0
  615. sbc X4,Y1
  616. sec
  617. div_13:
  618. rol Z0
  619. rol Z1
  620. rol Z2
  621. rol Z3
  622. rol Z4
  623.  
  624. dec wz_a1
  625. brne div_20
  626. ret
  627.  
  628. div_20:
  629. lsl X0
  630. rol X1
  631. rol X2
  632. rol X3
  633. rol X4
  634. rjmp div_10
  635.  
  636. normalize:
  637. ; shifts wy left as long as there is no leading '1' in wy
  638. ;number of needed shift operations +1 in wz_a1
  639. ldi wz_a1,1
  640.  
  641. n_10:
  642. sbrc Y1,7
  643. ret
  644.  
  645. rcall test_subtract
  646. brcs n_20
  647. ret
  648.  
  649. n_20:
  650. lsl Y0
  651. rol Y1
  652. inc wz_a1
  653. rjmp n_10
  654.  
  655. test_subtract:
  656. ; wx-wy - no data change
  657. ; C=0: wx<wy
  658. ; C=1: wx>=wy
  659. clc
  660. cpc X0,Y0
  661. cpc X1,Y1
  662. brcc ts_10
  663. clc
  664. ret
  665. ts_10:
  666. sec
  667. ret
  668.  
  669. subtract:
  670. ; wx-wy -> wx
  671. ; C=0: wx<wy
  672. ; C=1: wx>=wy
  673. clc
  674. sbc X0,Y0
  675. sbc X1,Y1
  676. ret
  677.  
  678. multiply_24_by_16:
  679. ; 24 bit rx x 16 bit ry => 40 bit rz
  680. clr Z0
  681. clr Z1
  682. clr Z2
  683. clr Z3
  684. clr Z4
  685.  
  686. ldi A,0x10
  687.  
  688. m_10:
  689. sbrs Y0,0
  690. rjmp m_20
  691.  
  692. add Z0,X0
  693. adc Z1,X1
  694. adc Z2,X2
  695. adc Z3,X3
  696. adc Z4,X4
  697.  
  698. m_20:
  699. lsr Y1
  700. ror Y0
  701.  
  702. lsl X0
  703. rol X1
  704. rol X2
  705. rol X3
  706. rol X4
  707.  
  708. dec A
  709. brne m_10
  710. ret
  711.  
  712.  
  713. SIN_TABLE:
  714. .DB 0x80,0x83
  715. .DB 0x86,0x89
  716. .DB 0x8C,0x90
  717. .DB 0x93,0x96
  718. .DB 0x99,0x9C
  719. .DB 0x9F,0xA2
  720. .DB 0xA5,0xA8
  721. .DB 0xAB,0xAE
  722. .DB 0xB1,0xB3
  723. .DB 0xB6,0xB9
  724. .DB 0xBC,0xBF
  725. .DB 0xC1,0xC4
  726. .DB 0xC7,0xC9
  727. .DB 0xCC,0xCE
  728. .DB 0xD1,0xD3
  729. .DB 0xD5,0xD8
  730. .DB 0xDA,0xDC
  731. .DB 0xDE,0xE0
  732. .DB 0xE2,0xE4
  733. .DB 0xE6,0xE8
  734. .DB 0xEA,0xEB
  735. .DB 0xED,0xEF
  736. .DB 0xF0,0xF1
  737. .DB 0xF3,0xF4
  738. .DB 0xF5,0xF6
  739. .DB 0xF8,0xF9
  740. .DB 0xFA,0xFA
  741. .DB 0xFB,0xFC
  742. .DB 0xFD,0xFD
  743. .DB 0xFE,0xFE
  744. .DB 0xFE,0xFF
  745. .DB 0xFF,0xFF
  746. .DB 0xFF,0xFF
  747. .DB 0xFF,0xFF
  748. .DB 0xFE,0xFE
  749. .DB 0xFE,0xFD
  750. .DB 0xFD,0xFC
  751. .DB 0xFB,0xFA
  752. .DB 0xFA,0xF9
  753. .DB 0xF8,0xF6
  754. .DB 0xF5,0xF4
  755. .DB 0xF3,0xF1
  756. .DB 0xF0,0xEF
  757. .DB 0xED,0xEB
  758. .DB 0xEA,0xE8
  759. .DB 0xE6,0xE4
  760. .DB 0xE2,0xE0
  761. .DB 0xDE,0xDC
  762. .DB 0xDA,0xD8
  763. .DB 0xD5,0xD3
  764. .DB 0xD1,0xCE
  765. .DB 0xCC,0xC9
  766. .DB 0xC7,0xC4
  767. .DB 0xC1,0xBF
  768. .DB 0xBC,0xB9
  769. .DB 0xB6,0xB3
  770. .DB 0xB1,0xAE
  771. .DB 0xAB,0xA8
  772. .DB 0xA5,0xA2
  773. .DB 0x9F,0x9C
  774. .DB 0x99,0x96
  775. .DB 0x93,0x90
  776. .DB 0x8C,0x89
  777. .DB 0x86,0x83
  778. .DB 0x80,0x7D
  779. .DB 0x7A,0x77
  780. .DB 0x74,0x70
  781. .DB 0x6D,0x6A
  782. .DB 0x67,0x64
  783. .DB 0x61,0x5E
  784. .DB 0x5B,0x58
  785. .DB 0x55,0x52
  786. .DB 0x4F,0x4D
  787. .DB 0x4A,0x47
  788. .DB 0x44,0x41
  789. .DB 0x3F,0x3C
  790. .DB 0x39,0x37
  791. .DB 0x34,0x32
  792. .DB 0x2F,0x2D
  793. .DB 0x2B,0x28
  794. .DB 0x26,0x24
  795. .DB 0x22,0x20
  796. .DB 0x1E,0x1C
  797. .DB 0x1A,0x18
  798. .DB 0x16,0x15
  799. .DB 0x13,0x11
  800. .DB 0x10,0x0F
  801. .DB 0x0D,0x0C
  802. .DB 0x0B,0x0A
  803. .DB 0x08,0x07
  804. .DB 0x06,0x06
  805. .DB 0x05,0x04
  806. .DB 0x03,0x03
  807. .DB 0x02,0x02
  808. .DB 0x02,0x01
  809. .DB 0x01,0x01
  810. .DB 0x01,0x01
  811. .DB 0x01,0x01
  812. .DB 0x02,0x02
  813. .DB 0x02,0x03
  814. .DB 0x03,0x04
  815. .DB 0x05,0x06
  816. .DB 0x06,0x07
  817. .DB 0x08,0x0A
  818. .DB 0x0B,0x0C
  819. .DB 0x0D,0x0F
  820. .DB 0x10,0x11
  821. .DB 0x13,0x15
  822. .DB 0x16,0x18
  823. .DB 0x1A,0x1C
  824. .DB 0x1E,0x20
  825. .DB 0x22,0x24
  826. .DB 0x26,0x28
  827. .DB 0x2B,0x2D
  828. .DB 0x2F,0x32
  829. .DB 0x34,0x37
  830. .DB 0x39,0x3C
  831. .DB 0x3F,0x41
  832. .DB 0x44,0x47
  833. .DB 0x4A,0x4D
  834. .DB 0x4F,0x52
  835. .DB 0x55,0x58
  836. .DB 0x5B,0x5E
  837. .DB 0x61,0x64
  838. .DB 0x67,0x6A
  839. .DB 0x6D,0x70
  840. .DB 0x74,0x77
  841. .DB 0x7A,0x7D
  842.  
  843.  
  844.  
  845.  
  846. kbd_state_engine:
  847. ;A
  848. .DB 0x00, 0x04, 0x08, 0x3c
  849. ;B
  850. .DB 0x00, 0x04, 0x3c, 0x12
  851. ;C
  852. .DB 0x00, 0x3c, 0x08, 0x15
  853. ;D
  854. .DB 0x3c, 0x18, 0x1c, 0x0c
  855. ;E
  856. .DB 0x3c, 0x18, 0x1c, 0x0c
  857. ;F
  858. .DB 0x3c, 0x18, 0x1c, 0x0c
  859. ;G
  860. .DB 0x21, 0x18, 0x3c, 0x0c
  861. ;H
  862. .DB 0x26, 0x3c, 0x1c, 0x0c
  863. ;K
  864. .DB 0x00, 0x04, 0x08, 0x3c
  865. ;L
  866. .DB 0x00, 0x04, 0x08, 0x3c
  867.  
  868.  
  869. .DSEG
  870. digit0: .BYTE 1
  871. digit1: .BYTE 1
  872. digit2: .BYTE 1
  873. digit3: .BYTE 1
  874. digit4: .BYTE 1
  875.  
  876. ;table: .BYTE tab_size ; reserve tab_size bytes.
Deutsch