X-Git-Url: https://git.gir.st/Chiptunes-pms150c.git/blobdiff_plain/29ec690644c48734d6732357e54d3dfbb82b07dd:/bsv.S..54babda0453493de38b5ff809f0a30c408fb8626:/bsv.asm diff --git a/bsv.S b/bsv.asm similarity index 80% rename from bsv.S rename to bsv.asm index b3a6ee5..e83e3a4 100644 --- a/bsv.S +++ b/bsv.asm @@ -54,6 +54,13 @@ ihrcr = 0x0B calib_freq = 4096000 ; Hz calib_vdd = 3000 ; mV +; Clock Parameters: +; during playback: IHRC/4, WDT off, keep ILRC on +active_clock = (( 0<<5 | 1<<4 | 0<<3 | 1<<2 | 0<<1 | 0<<0 )) +; during deep-sleep: ILRC/1, WDT off +sleep_clock = (( 7<<5 | 1<<4 | 0<<3 | 1<<2 | 0<<1 | 0<<0 )) +; for extra power saving, consider: 6<<5|0<<3 for ilrc/6, 2<<5|1<<3 for ilrc/16 + ; cycle count (worst-case) ; mod3: 28 ; g: 81 @@ -191,10 +198,10 @@ g: RET init: - ; clock setup (no calibration): + ; clock setup: SET1 clkmd, #4 ; enable IHRC - MOV a, #(( 0<<5 | 1<<4 | 0<<3 | 1<<2 | 0<<1 | 0<<0 )) - MOV clkmd, a ; switch to IHRC/4, WDT off; keep ILRC on + MOV a, #active_clock + MOV clkmd, a ; switch to IHRC ;; .org 0x46 ; comment out on 2nd iteration ; calibration placeholder: @@ -215,10 +222,10 @@ init: MOV sp, a ; portA setup: - MOV a, #0xff - MOV pac, a ; data direction: all output - MOV a, #0 - MOV padier, a ; disable pin wakeup + MOV a, #0x50 ; data direction: PWM & debug output, rest input + MOV pac, a ; (conserves power, apparently) + MOV a, #(( 1<<4 )) + MOV padier, a ; disable pin wakeup, except on audio pin MOV pa, a ; PortA data = 0 MOV paph, a ; disable all pull-ups @@ -228,9 +235,8 @@ init: ; highest "carrier frequency" for the PCM samples we can generate is by ; setting Timer2 to 6 bit, (IHRC/1)/1 mode, giving a frequency of ; (4*4.096MHz)/2^6 = 256kHz. - MOV a, #0x7f - MOV pwm, a - MOV tm2b, a ; pwm duty cycle 50% + MOV pwm, a ; clear + MOV tm2b, a ; clear MOV a, #(( 2<<4 | 3<<2 | 1<<1 | 0<<0 )) MOV tm2c, a ; timer2: IHRC, PA4, PWM, not inverted MOV a, #(( 0<<7 | 1<<5 | 0<<0 )) @@ -282,7 +288,8 @@ init: ENGINT loop: - ;TODO: test i2==0x78 to enter halt() + MOV a, i2 + CEQSN a, #0x78 ; compare, skip next if equal ; Note: usually, this is the place where the MCU is put into some ; sort of low power/sleep mode. But the Padauk's stopexe instruction ; causes the ISR to a) run at greatly reduced frequency (100hz vs @@ -292,9 +299,46 @@ loop: ; anyways). GOTO loop + ; at this point, i2==0x78, i.e. the music is finished. + ; => goto halt (fallthrough) +halt: + DISGINT + CLEAR i2 ; clear halting signal + + ; Note: disabling the timers isn't strictly necessary (as stopsys halts + ; all timers anyways), but I'm hoping it may reduce power consumption. + ; We're lucky that we only need to toggle a single bit to switch + ; between the required clock source and 'off' (0010xxxx->0000xxxx for + ; timer2, 100xxxxx->000xxxxx for timer16), so we can hack our way out + ; of loading an immediate each time. + SET0 tm2c, #5 + SET0 t16m, #7 + + SET1 pa, #4 ; assert a high level on the audio pin for good measure + SET0 pac, #4 ; ... before setting it to input mode (optional) + + ;switch to ilrc clock + MOV a, #sleep_clock + MOV clkmd, a + SET0 clkmd, #4 ; disable ihrc + + STOPSYS + ; (at this point, we wait for an i/o-toggle wake up event to resume execution) + + MOV a, #active_clock + MOV clkmd, a ; switch to IHRC again + + SET1 pac, #4 ; restore output mode for audio pin + + ;reenable timer16, timer2 + SET1 tm2c, #5 + SET1 t16m, #7 + + ENGINT + GOTO loop + interrupt: PUSH af - SET1 pa, #3 ;debug2 T1SN intrq, #2 ; if intrq.t16 is triggered, skip next GOTO ivr_end @@ -303,7 +347,7 @@ interrupt: SET1 pa, #6 ; debug - ;TODO: send pwm data to timer2 + ; send pwm data to timer2: MOV a, pwm ADD a, #4 MOV tm2b, a