; Disassembled by: ; DASMx object code disassembler ; (c) Copyright 1996-2003 Conquest Consultants ; Version 1.40 (Oct 18 2003) ; File: klm8048.bin ; Size: 1024 bytes ; Checksum: DFAD ; CRC-32: 130FB945 ; Date: Sun Mar 23 16:02:25 2014 ; CPU: Intel 8048 (MCS-48 family) ; tasm -48 -g3 klm8048.asm myklm8048.bin ; g0 is Intel Hex ; g3 selects binary ; Assembly source code for Korg PolySix D8048C Patch MCU ; Looks like one pass through all of the switches and pots takes 8.7 mSec (115 Hz) ; You can see this rate on pin 32 of the 8048 ; This file is valid input for TASM32 and will produce a binary that ; matches the original code. ; Note: Comments are mine, based on how I think the code works. ; There could easily be mistakes. ;8048 only has RAM from 0-3F rb0r0 .equ 00h ;first set of registers rb0r1 .equ 01h ;occupy RAM addresses 0-7 rb0r2 .equ 02h rb0r3 .equ 03h rb0r4 .equ 04h rb0r5 .equ 05h rb0r6 .equ 06h rb0r7 .equ 07h what1 .equ 08h what2 .equ 09h what3 .equ 0Ah what4 .equ 0Bh ;0C-13 get cleared when we rd or wr a patch to RAM ;that would put pots in edit mode what5 .equ 0Ch what6 .equ 0Dh limhit0to7 .equ 0Eh ;pot limit has been reached in this channel since prog ld limhit8toD .equ 0Fh ;same as above, but for ADC channels 8 to D absmde0to7 .equ 10h ;set if pot is in absolute mode, channel 0-7 absmde8toD .equ 11h ;set if pot is in absolute mode, channel 8-D D0D1swchgmsk .equ 12h ;1's mean switch has changed since program load ;so we update program based on switch value D2D3swchgmsk .equ 13h ;1's mean switch has changed since program load ;same as pots in absolute mode progLEDst .equ 14h ;current state of Program LED's 8-1? bankLEDst .equ 15h ;current state of WrEn Write Bank LED's? prgswst .equ 16h ;program sw states bnkswst .equ 17h ;bank, man, write, wr enab sw states ;second set of regs occupy RAM addr 24-31: rb1r0 .equ 18h rb1r1 .equ 19h rb1r2 .equ 1Ah rb1r3 .equ 1Bh rb1r4 .equ 1Ch rb1r5 .equ 1Dh rb1r6 .equ 1Eh ;pointer to current patch in external RAM page rb1r7 .equ 1Fh ;used to flash Write LED currpatch0 .equ 020h ;current patch data storage currpatch1 .equ 021h ;same order as 30-3F currpatch2 .equ 022h currpatch3 .equ 023h currpatch4 .equ 024h currpatch5 .equ 025h currpatch6 .equ 026h currpatch7 .equ 027h currpatch8 .equ 028h currpatch9 .equ 029h currpatchA .equ 02Ah currpatchB .equ 02Bh currpatchC .equ 02Ch currpatchD .equ 02Dh currpatchE .equ 02Eh currpatchF .equ 02Fh EffSpIntval .equ 030h ;current ADC results for the pots VCFcutval .equ 031h EGintval .equ 032h Resval .equ 033h Attval .equ 034h Decval .equ 035h Sustval .equ 036h Relval .equ 037h KBtrkval .equ 038h PWPWMval .equ 039h PWMSpval .equ 03Ah MGfreqval .equ 03Bh MGdelval .equ 03Ch MGlevval .equ 03Dh Swstates1 .equ 03Eh ;current VCO octave, Waveform, Sub Osc and Mod switch states Swstate2 .equ 03Fh ;current EG mode, Chorus Sel, VCA atten switch states .org 00000h L0000: anl p1,#01FH ;shut off P25,26,27 strobes clr a L0003: call L02D6 ;turn off all Program LED's call L02DC ;turn off Bank, Man, and Wr LED's mov psw,a L0008: in a,p1 jb4 L000D ;Test switch? (bit4 = 0) jmp L03B9 ;if so, jump L000D: ;Normal start-up code: sel rb1 ;select second reg bank mov r1,#014H mov a,#001H mov @r1,a ;init addr 0x14 to 1 (enable Program 1 LED) inc r1 mov @r1,a ;init addr 0x15 to 1 (enable Bank A LED) inc r1 clr a ;init addr 0x16 to 0 mov @r1,a inc r1 mov @r1,a ;init addr 0x17 to 0 mov r3,#040H mov r6,a ;clear rb1,r6 (sel patch 0) clr f0 ;select low page of external SRAM jmp L01C8 L0020: mov a,#00DH mov r7,a ;load rb0 r7 with 0x0D inc a mov r5,a ;rb0 r5 holds 0x0E (loop ctr) mov r6,#000H ;in this loop, r6 counts 0-D ;r7 counts 0D,0-C L0027: ;we must be in rb0 at this pt ;from here to P16 going high is 312 uSec ;(it's the DAC SAR time) call L021A ;perform ADC conv, r6 is chan, rlst in r4, acc mov a,#0FDH mov t,a strt t ;start timer (incs every 80 uSec) mov a,r7 outl p2,a ;select front panel analog mux channel ;and analog demux channel too add a,#020H ;add 0x20 to r7 value mov r0,a ;save sum in r0 mov a,@r0 ;read program value at this address outl bus,a ;and send it out on data bus orl p1,#040H ;raise P16/enable one of the 4051's ;channel we are sending out is different ;from channel we just converted, but we ;send out the correct patch data for it ;from here to where P16 drops is 240 uSec mov a,#020H add a,r6 ;add 0x20 to r6 value mov r0,a ;save sum in rb0 r0 mov r1,#010H ;put 0x10 in rb0 r1 mov a,#0F8H add a,r6 jc L0044 ;test for r6 > 7 mov a,r6 ;if it was > 7, use r6-8 value in acc jmp L0045 ;otherwise, use r6 value before subtraction ;we don't change r6 here L0044: inc r1 ;if r6>7 bump rb0 r1 to 0x11 L0045: add a,#0EFH movp3 a,@a ;get bit mask for r6 value (0-7) mov r3,a ;into r3 mov a,r1 ;get rb0 r1 into acc (either 0x10 or 0x11) sel rb1 add a,#0FCH ;-4 mov r1,a ;point rb1 r1 to 0x0C or 0x0D sel rb0 mov a,r3 ;get bitmask for r6 value anl a,@r1 ;test this bit in 0x10 or 0x11 address jnz L00A5 ;if it's set, jump to absolute mode end code dec r1 dec r1 ;point to either 0x0E or 0x0F mov a,@r1 anl a,r3 ;check bitmask bit at this address jz L006A ;jump if it's 0 mov a,#0FEH ;check conversion result for min value add a,r4 jnc L0073 ;if no cy, then r4 is 0 or 1 mov a,#002H add a,r4 ;if cy then r4 is 0xFE or 0xFF jc L0073 ;jump if pot is close to a limit inc r1 inc r1 ;point to either 0x10 or 0x11 mov a,@r1 orl a,r3 ;set bitmask bit at this address mov @r1,a ;probably this switches pot to absolute mode jmp L00A5 ;and jump to absolute mode end code L006A: ;jump here if pot has not reached limit yet mov a,r4 jz L0070 cpl a jnz L0073 L0070: ;we come here if r4 value is 0 or 0xFF mov a,@r1 orl a,r3 ;set bit to indicate limit has been reached mov @r1,a ;in 0x0E or 0x0F L0073: mov a,#030H add a,r6 mov r1,a mov a,@r1 ;get previous conversion value for this pot cpl a inc a ;negate it add a,r4 ;so acc = new conversion - previous value mov r2,a ;save this in r2 mov a,r3 ;get bit mask sel rb1 anl a,@r1 ;check bitmask bit in 0x0C or 0x0D sel rb0 jnz L0092 ;jump if it's set mov a,r2 jb7 L0087 ;if difference is negative jmp L0089 L0087: cpl a ;negate it inc a L0089: add a,#0FDH ;see if difference > 2 (pot has moved) jnc L00A7 ;jump if not mov a,r3 ;otherwise, get bit mask sel rb1 orl a,@r1 ;set bitmask bit in 0x0C or 0x0D mov @r1,a sel rb0 L0092: ;we may have jumped here mov a,r2 ;get difference jb7 L009C ;jump if it's negative add a,@r0 ;add positive difference to patch value for this channel jnc L00A0 ;if no overflow, jump clr a ;if overflow, cpl a ;load a with 0xFF jmp L00A0 L009C: add a,@r0 ;difference is negative, add it to patch value for this channel jc L00A0 ;if sum is negative clr a ;set value to 0 L00A0: mov @r0,a ;update patch value for this channel mov a,r4 mov @r1,a ;and update current value for this pot jmp L00A7 L00A5: ;this pot is in absolute mode mov a,r4 ;simply write conversion result mov @r0,a ;to patch location for this channel L00A7: jtf L00AB ;wait for timer flag to be set (240 uSec from start t?) jmp L00A7 ;if it's not, we loop L00AB: stop tcnt mov a,r6 ;save r6 in r7 mov r7,a inc r6 ;then bump r6 anl p1,#0BFH ;drop P16/inhibit both 4051's djnz r5,L0027 ;and loop ;code for switches that are stored with programs: mov r0,#02EH mov r1,#012H mov r5,#000H sel rb1 mov r0,#03EH ;low prog sw state byte mov r2,#0FEH mov r3,#010H sel rb0 mov r6,#002H L00C3: call L0230 ;read switch row sel by r2 0 bit and bit to left of it mov r4,a ;first row returned in low four bits sel rb1 xrl a,@r0 ;see if switch pos has changed sel rb0 mov r2,a ;save xor result mov a,#0C9H add a,r0 movp3 a,@a ;read from 0x3F7 table in ROM page 3 mov r7,a ;this is a loop ctr (first value is 0x04) L00CF: mov a,r5 add a,#0F9H movp3 a,@a ;read from 0x3F9 table in ROM page 3 mov r3,a ;first value is 0x03 anl a,@r1 ;use it as a mask against @r1 jnz L00DE mov a,r2 anl a,r3 ;AND xor result with mask jz L00E5 ;jump if switch pos matches prog sw state byte bits mov a,@r1 orl a,r3 ;otherwise, set mask bits in @r1 mov @r1,a L00DE: mov a,r3 cpl a ;invert mask from table anl a,@r0 ;clear bits in sw state byte, leave other switch bits in place xch a,r3 anl a,r4 ;AND mask with switch bits we read orl a,r3 ;OR in other sw state byte bits mov @r0,a ;and put it back in RAM L00E5: inc r5 djnz r7,L00CF mov a,@r0 ;send out updated sw state byte to hw outl bus,a inc r0 inc r1 sel rb1 in a,p2 ;send P24 or P25 stb high orl a,r3 outl p2,a inc r0 mov a,r3 rl a ;rotate stb select from P24 to P25 mov r3,a sel rb0 anl p2,#00FH ;shut off P24 or P25 stb djnz r6,L00C3 ;loop jni L00FD ;interrupt hooks to tape enable switch (0 = tape enabled) jmp L00FF L00FD: jmp L031E ;tape is enabled L00FF: ;from L0020 to here is 8.37 mSec) orl p1,#020H ;bring P15 test pt signal high (here to end of loop is 343 uSec) mov r1,#016H ;read program number switches call L0230 ;read switch row sel by r2 0 bit and bit to left of it ;first row returned in low 4 bits, 1 means sw pressed xch a,@r1 ;update address 0x16 with current sw status cpl a ;any switches that were pressed before will now be 0's anl a,@r1 ;so this gives us only the switches that were just pressed jnz L010C jmp L012E L010C: mov r2,#0FFH L010E: inc r2 rrc a ;get bit pos of rightmost one bit (0-7) jnc L010E dec r1 ;point to address 0x15 mov a,#0EFH anl a,@r1 ;clear bit 4 mov @r1,a ;and update it mov r3,a ;save a copy in r3 dec r1 ;point to address 0x14 mov a,#0EFH add a,r2 movp3 a,@a ;get bit mask for r2 value (0-7) into acc mov @r1,a ;put bit mask for program into addr 0x14 (turn on the correct LED) mov a,r2 ;get program # - 1 (0-7) value swap a ;multiply it by 16 sel rb1 xch a,r6 ;put it in rb1 r6 anl a,#080H ;get D7 of old rb1 r6 value orl a,r6 mov r6,a ;and put it back into rb1 r6 sel rb0 mov a,#020H anl a,r3 ;check bit 5 of r3 (addr 15 value from before, so Write LED bit) jnz L01AF ;if set, save patch in external SRAM, using rb1 r6 as dest jmp L01C7 ;otherwise, read patch from external RAM using rb1 r6 as srce addr L012E: ;we jump here if no program switches are newly pressed inc r1 ;point to 0x17 ;now read Bank, Manual, Write, and Write Enable Switches call L0230 ;read switch row sel by r2 0 bit and bit to left of it xch a,@r1 ;update address 0x17 with current sw status cpl a ;any switches that were pressed before will now be 0's anl a,@r1 ;so this gives us only the switches that were just pressed mov r4,a ;save result mov a,#040H anl a,@r1 ;get D6 of new switch state (Write enable) orl a,r4 ;OR it into change result mov r4,a ;and save that in r4 dec r1 dec r1 ;r1 points to 0x15 now anl a,#00FH ;check for bank switches newly pressed jz L016F ;jump if none newly pressed mov r2,#0FFH ;bank switch was just pressed: L0142: inc r2 rrc a jnc L0142 ;get bit pos of rightmost 1 bit in bank switch positions mov a,#0EFH add a,r2 movp3 a,@a ;get bit mask for r2 value (0-7) into acc xch a,@r1 ;update addr 0x15 with curr bank bit mask anl a,#0F0H ;clear out any previous bank mask bits orl a,@r1 ;OR in new bank bit mask mov @r1,a ;and update addr 0x15 value (turn on correct Bank LED) mov r3,a ;save it in r3 also mov a,r2 ;get bank sw bit pos (0-3) cpl a ;invert bits clr f0 ;select low page of external SRAM jb1 L0156 ;if bank was 0 or 1, bit 1 is now set ;so we leave f0 flag cleared cpl f0 ;if it was 2 or 3, set flag to ;select high page of external SRAM ;(checked when we read or write to external SRAM) L0156: sel rb1 jb0 L015E ;if bank was 0 or 2, bit is is now set mov a,#080H ;new bank is 1 or 3, so set rb1 r6 bit 7 orl a,r6 jmp L0161 L015E: ;new bank is 0 or 2, so clear rb1 r6 bit 7 mov a,#070H anl a,r6 L0161: mov r6,a ;update rb1 r6 (ptr to current program in SRAM page) sel rb0 mov a,#020H anl a,r3 ;check write LED bit in 0x15 addr (also in r3) jnz L018D mov a,#010H anl a,r3 ;check manual LED bit in 0x15 addr (also in r3) jnz L0186 jmp L01C7 ;read patch from external RAM using rb1 r6 as srce addr L016F: ;we jump here if no new bank has been selected mov a,#010H ;r4 has newly pressed switches as 1's anl a,r4 ;check for Manual switch pressed jz L0186 ;skip if not mov a,@r1 ;manual switch was pressed, read addr 0x15 orl a,#010H ;set D4 bit (turn on Manual LED?) anl a,#0DFH ;and clear D5 bit (make sure Write LED is off) mov @r1,a ;update addr 0x15 dec r1 ;point to addr 0x14 clr a mov @r1,a ;clear it (Turn off all program LED's) cpl a mov r0,#004H L0180: dec r1 ;and set addr 0x13, 0x12, 0x11, 0x10 to 0xFF's mov @r1,a ;this puts all pots and switches in absolute mode djnz r0,L0180 ;so we are updating the program directly with their jmp L0204 ;values, (we always send the program to the hw) L0186: mov r1,#015H ;we come here if manual sw not newly pressed mov a,#020H ;check Write LED state? anl a,@r1 jz L0198 L018D: ;we come here if Write LED is on mov a,r4 anl a,#040H jz L01A9 sel rb1 mov a,#005H ;bump rb1 r7, used to flash Write LED add a,r7 jmp L01A6 L0198: mov a,r4 cpl a anl a,#060H jz L01A0 ;if both write and write enable "pressed" bits are set, jump jmp L0204 ;(write enable "pressed" bit is set whenever Write Enable LED is on) L01A0: mov a,@r1 orl a,#020H ;turn on Write LED mov @r1,a sel rb1 clr a ;clear acc L01A6: mov r7,a ;move acc into rb1 r7, if we jumped here after L018D jmp L0204 ;then we are adding 5 to r7 L01A9: mov a,@r1 ;clear bit D5 at @r1 address, jump to L0204 anl a,#0DFH mov @r1,a jmp L0204 L01AF: ;copies 16 bytes from address 0x020 into ext SRAM sel rb1 ;dest address is rb1 r6 mov r0,#020H ;start of current patch storage in 8048 RAM mov a,r6 ;external RAM storage location ptr mov r1,a clr a jf0 L01B9 ;flag0 selects low or high page of SRAM jmp L01BB L01B9: orl a,#002H L01BB: outl p2,a mov r5,#010H ;copy 16 bytes into external SRAM (one program) L01BE: mov a,@r0 call L0258 ;write acc to external SRAM byte pointed to by r1 inc r0 djnz r5,L01BE sel rb0 jmp L01DE L01C7: ;copies 16 bytes from ext SRAM into address 0x20 sel rb1 ;src addr is rb1 r6 L01C8: mov r0,#020H ;current patch location in 8048 RAM? mov a,r6 ;external RAM storage location ptr mov r1,a mov a,#001H jf0 L01D2 ;flag0 selects low or high page of SRAM jmp L01D4 L01D2: orl a,#002H L01D4: outl p2,a mov r5,#010H ;copy 16 bytes into 8048 RAM (one program) L01D7: call L0245 ;read external SRAM byte pointed to by r1 into acc mov @r0,a inc r0 djnz r5,L01D7 sel rb0 L01DE: mov r1,#00CH ;clear eight bytes starting at addr 0x0C clr a mov r2,#008H L01E3: mov @r1,a inc r1 djnz r2,L01E3 mov r6,#000H mov r0,#030H ;starting address for conversion results mov r5,#00EH ;14 front panel pots to convert L01ED: call L021A ;perform ADC conv, r6 is chan, rlst in r4, acc mov @r0,a inc r0 inc r6 djnz r5,L01ED ;do all 14 conversions and save results mov r0,#03EH sel rb1 mov r2,#0FEH call L0230 ;read VCO octave, Waveform, Sub Osc and Mod switch states (D0,D1) mov @r0,a ;and save with pot values inc r0 call L0230 ;read EG mode, Chorus Sel, VCA atten switch states (D2,D3) mov @r0,a ;and save with pot values mov r1,#015H jmp L01A9 ;clear bit D5 at @r1 address (Turn off Write LED), jump to L0204 L0204: sel rb1 mov r0,#014H mov a,@r0 ;send value at address 14 to Program LED's call L02D6 ;write acc contents to Program LED's, 1=on inc r0 ;r0 = 0x15 mov a,r7 ;if rb1 r7 bits 7 and 6 are both 1 rr a anl a,r7 ;then bit 6 will be 1 here rr a ;and will be bit 5 here anl a,#020H ;AND with 0x20 (only leave D5) cpl a ;invert, if D5 was set it will be off now anl a,@r0 ;AND result with Bank, Man, and write LED state in RAM call L02DC ;write acc to Bank (0-3), Man(4) and Write(5) LED's sel rb0 anl p1,#0DFH ;drop P15 test point signal (This shows how long each pass takes) jmp L0020 ;jump back to start of main loop L021A: ;successive approx ADC routine mov a,r6 ;channel to convert anl a,#00FH ;keep stbs off outl p2,a mov r3,#080H ;starting DAC value clr a mov r4,a ;conversion result mov r2,#008H ;number of bits L0224: add a,r3 ;add in bit we are testing outl bus,a ;send current result to DAC xch a,r3 rr a ;rotate test bit to right xch a,r3 jnt0 L022C ;if that bit makes DAC > pot, don't add it in ;t0=0 means DAC > pot mov r4,a ;otherwise, update result to include that bit L022C: mov a,r4 ;get result into acc djnz r2,L0224 ;iterate over 8 bits ret L0230: ;reads two 4-bit switch state values from hw sel rb1 ;and combines them into a byte mov a,r2 ;value in rb1 r2 determines which switches we read outl bus,a ;only one bit is low at a time, and goes out on D0-D7 rl a mov r2,a in a,p1 orl a,#0F0H mov r5,a mov a,r2 outl bus,a rl a mov r2,a in a,p1 swap a orl a,#00FH anl a,r5 cpl a ;invert switch levels to make them active high sel rb0 ret L0245: ;reads byte pointed to by r1 from external 4-bit SRAM ;which is used as two banks of 256 bytes ;P21 selects bank0 or bank 1 of SRAM ;byte is returned in acc orl p1,#080H ;enable external RAM chip select anl p2,#0FEH ;clear A0, select low nibble movx a,@r1 ;read low nibble anl a,#00FH ;low 4 bits only mov r2,a ;save it orl p2,#001H ;set A0, select high nibble movx a,@r1 ;read high nibble anl p1,#07FH ;disable external RAM chip select swap a ;put nibble in high bits anl a,#0F0H ;clear out low bits orl a,r2 ;OR in low nibble inc r1 ;inc ptr? ret L0258: ;writes byte in acc to external SRAM ;which is used as two banks of 256 bytes ;P21 selects bank0 or bank 1 of SRAM orl p1,#080H ;enable external RAM chip select anl p2,#0FEH ;clear A0, select low nibble movx @r1,a ;write low nibble swap a ;swap nibbles orl p2,#001H ;set A0, select high nibble movx @r1,a ;write high nibble anl p1,#07FH ;disable external RAM chip select inc r1 ;inc ptr? ret ;; **************** Start of tape Load/Store/Verify routines ***************************** L0265: ;receive a byte from tape call L0274 jc L0265 mov r7,#008H ;bit count L026B: call L0274 ;get one bit xch a,r3 rrc a ;rotate it into r3, lsbit is first xch a,r3 djnz r7,L026B mov a,r3 ;put byte in acc ret L0274: ;get one bit from tape input clr c mov r2,#000H ;set loop limit? jf1 L027F L0279: jt1 L0287 ;t1 is tape input comparator signal djnz r2,L0279 jmp L0283 L027F: jnt1 L0287 ;t1 is tape input comparator signal djnz r2,L027F L0283: mov r5,#001H mov r6,#001H L0287: cpl f1 jtf L028B ;jump if timer has overflowed cpl c L028B: mov a,#0FAH mov t,a call L02E2 ret ;end of get one tape bit L0291: ;sends byte in acc to tape mov r3,a clr c call L02A5 ;send 0 bit (cy) mov r7,#008H ;bit counter L0297: mov a,r3 rrc a mov r3,a call L02A5 ;send 8 bits, lsb first djnz r7,L0297 clr c cpl c ;set cy call L02A5 ;send 1 bit call L02A5 ;send 1 bit ret L02A5: call L02F0 ;check for cancel sw or tape no longer enabled in a,p2 jb2 L02AE orl a,#00CH jmp L02B0 L02AE: anl a,#003H L02B0: mov r2,a mov a,#0FCH jc L02BA rlc a xch a,r2 xrl a,#008H xch a,r2 L02BA: jtf L02BE jmp L02BA L02BE: mov t,a mov a,r2 outl p2,a ret L02C2: call L0265 ;receive a byte from tape xrl a,#050H ;check for first header byte jnz L02C2 ;restart if no match call L0265 ;receive a byte from tape xrl a,#036H ;check for second header byte jnz L02C2 ;restart if no match ret ;return if we got header L02CF: mov r0,#000H mov r5,#002H anl p2,#0FDH ;clear P21 output ret L02D6: ;write acc contents to Program LED's outl bus,a ;1 turns on LED orl p2,#040H ;P26 is stb for Program LED's 1-8 anl p2,#0BFH ret L02DC: ;write acc contents to Bank LED's, Man and Wr outl bus,a ;0=on, D0-3 are Bank, D4 is manual, D5 is Write orl p2,#080H ;P27 is stb for Bank LED's, Man, Wr anl p2,#07FH ret L02E2: jf0 L02E6 jmp L02F0 L02E6: mov a,#07FH outl bus,a ;send D7 low in a,p1 ;read a row of matrix switches jb2 L02EE ;check Write Enable switch jmp L02F0 L02EE: jmp L031E ;if write enable sw open L02F0: jni L02F4 ;interrupt hooks to tape enable switch (0 = tape enabled) jmp L0000 ;if input is 0, jni will jump L02F4: ;read tape switches/check for cancel mov a,#0BFH outl bus,a ;send D6 low in a,p1 ;read tape-related matrix switches jb3 L02FC ;check Error/Cancel switch jmp L031E ;jump to start of tape code if it's pressed L02FC: ;otherwise ret ret L02FD: call L02DC ;write acc to Bank (0-3), Man(4) and Write(5) LED's clr a mov r4,a ;turn off all program LED's call L02D6 ;write acc contents to Program LED's, 1=on strt t ret L0305: ;this code fills program LEDs to indicate mov a,#0C0H ;tape operation progress orl a,r1 cpl a jnz L0312 ;only update LED's if r1[5:0] == 0x3F (once every 64 bytes) mov a,r4 clr c cpl c ;set cy flag rlc a ;rotate it left into acc mov r4,a ;r4 holds LED's state call L02D6 ;write acc contents to Program LED's, 1=on L0312: ret L0313: clr c cpl c ;set cy flag mov r7,#000H L0317: call L02A5 djnz r7,L0317 djnz r6,L0317 ret L031E: ;we come here if tape is enabled clr a ;turn off all 12 KLM-367 LED's call L02D6 ;write acc contents to Program LED's, 1=on call L02DC ;write acc to Bank (0-3), Man(4) and Write(5) LED's mov psw,a L0324: clr f0 ;select low page of external SRAM stop tcnt ;stop the timer call L02F0 ;restart if tape no longer enabled, otherwise read tape switches cpl a ;which are active low jb0 L0331 ;"To Tape" pressed, so do tape send operation jb2 L038C ;"Verify" pressed jb1 L0361 ;"From Tape" pressed, so do tape receive jmp L0324 ;no tape switches pressed yet, so wait for one L0331: ;tape send operation mov a,#001H call L02FD ;turn on Bank A/To Tape LED, turn off all program LED's, zero r4 mov r6,#028H call L0313 mov a,#050H call L0291 ;send 0x50 byte to tape mov a,#036H call L0291 ;send 0x36 byte to tape call L02CF ;set r5 to 2, clear P21 jmp L0347 L0345: orl p2,#002H ;for second pass we set top address bit (P21) L0347: mov r6,#000H mov r1,#000H L034B: call L0245 ;read external SRAM byte pointed to by r1 into acc xch a,r0 add a,r0 xch a,r0 ;r0 = r0 + acc (checksum?) call L0291 ;transmit acc byte to tape call L0305 ;show tape operation progress on LEDs, only incs LEDs when r1=0x3F djnz r6,L034B djnz r5,L0345 mov a,r0 call L0291 ;send checksum at the end mov r6,#006H call L0313 jmp L031E ;stay in tape code L0361: ;should be tape receive code cpl f0 call L02E2 mov a,#002H call L02FD ;turn off "From Tape, turn off all program LED's, zero r4 call L02C2 ;wait for two-byte header mov a,#032H ;turn on "From Tape", Manual and Write LED's call L02DC ;write acc to Bank (0-3), Man(4) and Write(5) LED's call L02CF ;set r5 to 2, clear P21 jmp L0374 L0372: orl p2,#002H ;write to second page on second pass L0374: mov r6,#000H mov r1,#000H L0378: call L0265 ;receive a byte from tape xch a,r0 add a,r0 ;add it to checksum xch a,r0 call L0258 ;write acc to external SRAM byte pointed to by r1 call L0305 ;show tape operation progress on LEDs, only incs LEDs when r1=0x3F djnz r6,L0378 djnz r5,L0372 ;write two pages of 256 bytes each L0385: call L0265 ;receive checksum byte from tape xrl a,r0 ;compare to computed checksum jnz L03B3 ;err if not equal jmp L031E ;stay in tape code L038C: ;Tape verify code mov a,#004H call L02FD ;turn on "Verify" LED, turn off program LED's, zero r4 call L02C2 ;wait for two-byte header mov a,#014H ;turn on "Manual" and "Verify" LED's call L02DC ;write acc to Bank (0-3), Man(4) and Write(5) LED's call L02CF ;set r5 to 2, clear P21 jmp L039C L039A: orl p2,#002H ;read second page on second pass L039C: mov r6,#000H mov r1,#000H L03A0: call L0265 ;receive a byte from tape xch a,r0 add a,r0 ;add it to checksum xch a,r0 mov r3,a ;and save in r3 call L0245 ;read external SRAM byte pointed to by r1 into acc xrl a,r3 ;compare to rec'd byte jnz L03B3 ;err if not equal call L0305 ;show tape operation progress on LEDs, only incs LEDs when r1=0x3F djnz r6,L03A0 djnz r5,L039A ;read two pages of 256 bytes each jmp L0385 L03B3: ;Verify Failed mov a,#008H ;turn on "Error/Cancel" LED call L02DC ;write acc to Bank (0-3), Man(4) and Write(5) LED's jmp L0324 ;back to tape code ;; **************** End of tape Load/Store/Verify routines ***************************** L03B9: ;DAC Calibration code: mov r0,#00CH L03BB: mov r1,#00CH mov r6,#000H ;select chan 0 (Eff Spd/Int=0, or -5V) call L021A ;perform ADC conv, r6 is chan, rlst in r4, acc call L03D9 ;conversion result around 0 inc r1 inc r6 ;select chan 1 (Filt Cutoff=10, or +5V) call L021A ;perform ADC conv, r6 is chan, rlst in r4, acc cpl a ;conversion result around 0xFF, so invert it call L03D9 mov r2,#004H L03CC: xch a,@r1 rlc a ;rotate @r1 left one bit through cy xch a,@r1 xch a,@r0 rrc a ;rotate @r0 right one bit, shifting in msbit of @r1 xch a,@r0 djnz r2,L03CC ;seems like they wanted D4 set to get 10000001 after rotating mov a,@r0 call L02D6 ;send acc to Program 1-8 LEDs, 1=on jmp L03BB ;and loop L03D9: jnz L03DE mov @r1,#010H ;if conversion result = 0, set D4 ret L03DE: add a,#0FEH jc L03E5 mov @r1,#020H ;if conversion result < 2, set D5 ret L03E5: add a,#0FEH ;if conversion result was < 4, set D6 jc L03EC mov @r1,#040H ret L03EC: ;if conversion result was >= 4, set D7 mov @r1,#080H ret ;end of DAC calibration code L03EF: .db 001h ;bitmask table .db 002h .db 004h .db 008h .db 010h .db 020h .db 040h .db 080h L03F7: .db 004h ;these end up being loop ctrs to read the values .db 003h ;in the next table, which are bit masks for some switches ;combine these four values and you get all of the bits ;in a byte. These are masks for the switch/contr reg hw. L03F9: .db 003h ;octave switch .db 00Ch ;waveform select .db 030h ;sub harmonic .db 0C0H ;modulation destination select .db 001H ;EG Mode .db 00Eh ;Chorus/Phaser .db 0F0h ;VCA Attenuation .end