;.area DATA .area OSEG (OVR,DATA) ;.area DATA notes: .ds 16 ; 0x00 .. 0x0f i0: .ds 1 ; 0x10 i1: .ds 1 ; 0x11 i2: .ds 1 ; 0x12 n: .ds 1 ; 0x13 .even ; make next two bytes word-aligned zero: .ds 1 ; 0x14 tmp_1: .ds 1 ; 0x15 tmp_hi: .ds 1 ; 0x16 tmp_lo: .ds 1 ; 0x17 pwm: .ds 1 ; 0x18 .area SSEG .even ; SP must be aligned? (sdcc does it) stack: .ds 1 ; aliases for memory locations: notes_ix = tmp_1 t = tmp_1 mul2 = tmp_hi mul1 = tmp_lo mod3hi = tmp_hi mod3lo = tmp_lo ; cycle count (worst-case) ; mod3: 28 ; g: 81 ; sample: 115 + 4*g + 2*mod3 = 495 .area CSEG (CODE,ABS) ;.area HOME ;.area HEADER (ABS) .org 0x0000 ;TODO: 0x0000 must be NOP for autocalib routine ;TODO: move some init stuff here (space for 15 instr.) GOTO init ;.area HOME ;.area HEADER (ABS) .org 0x0020 GOTO sample ;.area CODE mod3: MOV a, mod3hi ADD mod3lo, a ; mod3lo = hi+lo MOV a, #0 ADDC a ; mod3hi, 1bit SWAP a MOV mod3hi, a MOV a, mod3lo SWAP a AND a, #0xf ; (mod3lo>>4) XCH mod3lo ; a=mod3lo, mod3lo=mod3lo>>4 AND a, #0xF ; a=mod3lo&0xf, mod3lo=mod3lo>>4 ADD a, mod3lo ; (mod3lo & 0xF) ADD a, mod3hi MOV mod3lo, a AND a, #0x3 ; a = (mod3lo & 0x3) SR mod3lo SR mod3lo ; (mod3lo >> 2) ADD a, mod3lo MOV mod3lo, a AND a, #0x3 ; a = (mod3lo & 0x3) SR mod3lo SR mod3lo ; (mod3lo >> 2) ADD a, mod3lo SUB a, #3 T0SN f, c ADD a, #3 RET g: ; notes_ix_hi = always 0 AND a, #0x7 MOV notes_ix, a ; test i2 & 3: MOV a, i2 AND a, #3 T0SN f, z SET1 notes_ix, #3 IDXM a, notes_ix MOV t, a CLEAR mul2 CLEAR mul1 ; note: LSB of result (mul0) is not needed for our purposes ;;1/8: SR t T1SN f, c GOTO skip1 MOV a, i0 ADD mul1, a MOV a, i1 ADDC mul2, a skip1: SR mul2 SRC mul1 ;;2/8: SR t skip2: SR mul2 SRC mul1 ;;3/8: SR t T1SN f, c GOTO skip3 MOV a, i0 ADD mul1, a MOV a, i1 ADDC mul2, a skip3: SR mul2 SRC mul1 ;;4/8: SR t T1SN f, c GOTO skip4 MOV a, i0 ADD mul1, a MOV a, i1 ADDC mul2, a skip4: SR mul2 SRC mul1 ;;5/8: SR t T1SN f, c GOTO skip5 MOV a, i0 ADD mul1, a MOV a, i1 ADDC mul2, a skip5: SR mul2 SRC mul1 ;;6/8: SR t T1SN f, c GOTO skip6 MOV a, i0 ADD mul1, a skip6: SRC mul1 ;;7/8: SR t T1SN f, c GOTO skip7 MOV a, i0 ADD mul1, a skip7: SRC mul1 ;;8/8: SR t T1SN f, c GOTO skip8 MOV a, i0 ADD mul1, a skip8: SRC mul1 MOV a, mul1 RET init: ; AUTO_INIT_SYSCLOCK() -- 4mhz ; AUTO_CALIBRATE_SYSCLOCK() -- move away w/ goto ; ??: setup fuses (romlocation 0x3ff) ; setup SP (&= 0xfe) ; setup timer2, timer16 CLEAR i0 CLEAR i1 CLEAR i2 ;rom is not mmapped; must load into ram first MOV a, #0x84 MOV notes+0x0, a MOV notes+0x5, a MOV a, #0x9d MOV notes+0x1, a MOV notes+0x4, a MOV a, #0xb0 MOV notes+0x2, a MOV notes+0xA, a MOV a, #0x69 MOV notes+0x3, a MOV notes+0x6, a MOV notes+0xB, a MOV notes+0xE, a MOV a, #0x58 MOV notes+0x7, a MOV notes+0xF, a MOV a, #0x75 MOV notes+0x8, a MOV notes+0xD, a MOV a, #0x8c MOV notes+0x9, a MOV notes+0xC, a ;TODO: setup mcu, timer16, ... ;TODO: freepdk calibration routine loop: ;TODO: test i2==0x78 to enter halt() ;TODO: stopsys GOTO loop sample: ;TODO: send pwm data to timer2 MOV a, i2; "mov mem,mem" MOV n, a; does not exist SL n SL n MOV a, i1 SWAP a AND a, #0xf SR a SR a OR n, a MOV a, n CALL g SWAP a AND a, #0x1 MOV pwm, a MOV a, i2 SL a SL a SL a MOV tmp_1, a ; fresh tmp_1: MOV a, i1 SWAP a AND a, #0xf SR a OR a, tmp_1 ; tmp_1 done. XOR a, n CALL g SR a AND a, i2 SR a AND a, #3 ADD pwm, a MOV a, i2 MOV mod3hi, a SR mod3hi SR mod3hi SR mod3hi SWAP a AND a, #0xf0 SL a MOV mod3lo, a MOV a, i1 SR a SR a SR a OR mod3lo, a CALL mod3 ADD a, n CALL g SR a SR a MOV tmp_1, a ; a saved in tmp_1; fresh a MOV a, i2 ; shift-divide by six ; note: i2 is max 0x78; so a will <= 20. (breaks vor values >=128) SR a ADD a, i2 SR a SR a ADD a, i2 SR a SR a ADD a, i2 SR a SR a SR a ; end divide by six AND a, tmp_1 ; a restored from tmp_1 AND a, #3 ADD pwm, a MOV a, i2 MOV mod3hi, a SR mod3hi SR mod3hi SWAP a AND a, #0xf0 SL a SL a MOV mod3lo, a MOV a, i1 SR a SR a OR mod3lo, a CALL mod3 SUB a, n SUB a, #8 NEG a CALL g SR a MOV tmp_1, a ; a saved in tmp_1; fresh a MOV a, i2 ; shift-divide by ten ; note: i2 is max 0x78; so a will <= 12. INC i2 SR a ADD a, i2 SR a SR a SR a ADD a, i2 SR a ADD a, i2 SWAP a DEC i2 ; end divide by ten AND a, tmp_1 ; a restored from tmp_1 AND a, #3 ADD pwm, a MOV a, pwm SWAP a ; next sample is now ready. INC i0 ADDC i1 ADDC i2 RETI