as12 (v1.2a) absolute assembler for the Motorola CPU12 Executed: Mon Apr 12 00:36:15 2004 0000 Reg_Block EQU $00 1000 Loader_Start EQU $1000 0020 WordLength EQU 32 ; This is the length of the word the BCD routine works with. 0005 BytesOut EQU 5 ; The number of result bytes we expect from the BCD converter. * IDE Register Addresses 0b80 IDE_Data_Lo EQU $0B80 0b90 IDE_Data_Hi EQU $0B90 0b87 IDE_Status EQU $0B87 0b8e IDE_AltStatus EQU $0B8E * SCI0_Flags Bit Definitions 0001 Getting_Input EQU 001 0002 Input_Taken EQU 002 0020 Dumping_Value EQU 032 0040 Writing_Value EQU 064 0080 Reading_Value EQU 128 * Sys_Flags_0 Bit Definitions 0001 Array_Parsing EQU 001 0002 Out_Waiting EQU 002 *************************************************************************** * Variables Start Here * *************************************************************************** 3000 ORG $3000 3000 Large_ASCII RMB 2048 3800 IDE_R_Buffer RMB 4096 4800 IDE_W_Buffer RMB 4096 5800 Total_Sectors RMB 4 0000 ORG $0000 ; Bottom of internal RAM. 0000 LBA_Pointer RMB 4 ; Holds the LBA. 0004 Read_Pointer RMB 2 ; Pointer to the buffer for IDE Reads. 0006 Bytes_Moved RMB 2 ; Counts how many bytes were transfered. 0008 ByteCount RMB 1 ; Used for the BCD conversion routine. 0009 Bytes RMB 5 ; This is where the packed-BCD gets put. 000e BitCount RMB 1 ; Used for the BCD conversion routine. 000f RESULT RMB 4 ; This is the 32-bit field used by HEX_2_BCD. 0013 Sys_Flags_0 RMB 1 ; Sys_Flags helps keep the program in line. 0014 SCI0_Flags RMB 1 0015 SCIBuf_Pointer RMB 2 ; Pointer to the next byte to be sent out of SCI0 (A UI thing). 0017 ASCII_BUF RMB 12 0023 UserInput_Buf RMB 4 0027 CharactersLeft RMB 1 0028 Effective_ADR RMB 2 *************************************************************************** * Executable code starts here. * *************************************************************************** c000 ORG $C000 c000 18 0b 08 00 11 RESET: MOVB #$08,$0011 ; Map 512-byte register block to 0x0800 c005 a7 NOP c006 87 CLRA c007 7a 08 10 STAA $0810 ; Internal 1024-bytes of RAM are at 0x0000 c00a 7a 08 16 STAA $0816 ; No clock monitor or COP. c00d b6 08 12 LDAA $0812 ; Take the internal EEPROM out of the memory c010 84 fe ANDA #$FE ; map so the space can be used for RAM. c012 7a 08 12 STAA $0812 * Expanded Memory Init c015 18 0b 04 08 0a MOVB #$04,$080A ;enable read/write signal (PEAR) c01a 18 0b b0 08 0b MOVB #$B0,$080B ;normal exp. narrow (MODE) c01f 18 0b e0 08 37 MOVB #$E0,$0837 ;enable data, extra, & program windows (WINDEF) c024 18 0b 07 08 38 MOVB #$07,$0838 ;enable A16, A17, A18 (MXAR) c029 18 0b 34 08 3c MOVB #$34,$083C ;enable CS2E, CSD & CSP0 (CSCTL0) CS2: 0x0B80 - 0xBFF c02e 18 0b 10 08 3d MOVB #$10,$083D ;CSD covers lower half of memory map (CSCTL1) c033 cf 02 00 LDS #$0200 ; Stack points to top of RAM. c036 18 0b 00 08 35 MOVB #$00,$0835 ; Set Program page to page 0 (PPAGE) * A/D Converter Init c03b 18 0b c2 08 62 MOVB #$C2,$0862 ; Enable ATD, Fast clear, and Interrupt (ATDCTL2) c040 18 0b 67 08 64 MOVB #$67,$0864 ; (ATDCTL4). Slowest possible sample rate is at 67. c045 18 0b 70 08 65 MOVB #$70,$0865 ; 8 channel mode, continuous scan all channels (ATDCTL5) * Asynchronous Serial Sub-system Init c04a 18 0b 00 08 c2 MOVB #$00,$08C2 ; (SC0CR1) Set up SCI0 for PC c04f 18 0b 10 08 ca MOVB #$10,$08CA ; (SC1CR1) Set up SCI1 for DMX512 c054 18 0b 2c 08 c3 MOVB #$2C,$08C3 ; (SC0CR2) Transmitter and Receiver on RIE on. $2C for IRQ c059 18 0b 88 08 cb MOVB #$88,$08CB ; (SC1CR2) No receiver. TIE on. c05e 18 03 00 34 08 c0 MOVW #$0034,$08C0 ; (SCI0BD) ~9600bps c064 18 03 00 02 08 c8 MOVW #$0002,$08C8 ; (SCI1BD) 250000bps c06a b6 08 c4 LDAA $08C4 ; read register to clear flag RDRF c06d b6 08 c7 LDAA $08C7 ; dummy read to flush receive buffer c070 18 0b 40 08 ce MOVB #$40,$08CE ; set the 9th bit to act as a second stop bit. c075 18 0b 03 08 af MOVB #%00000011,$08AF ; PORTT is High-Output Low-Input (DDRT) c07a 18 0b 03 08 ae MOVB #%00000011,$08AE ; PORTT is now prepped for use. c07f 18 0b 40 08 09 MOVB #%01000000,$0809 ; PORTE DDR bit 6 is output. c084 18 0b 40 08 08 MOVB #%01000000,$0808 ; PORTE(6) is now high. c089 ce 00 00 LDX #0000 ; \ Zero-out all the variables. c08c 87 CLRA ; | c08d 6a 30 Zero_Loop: STAA $01,X+ ; | c08f 8e 00 29 CPX #Effective_ADR+1 ; | c092 26 f9 BNE Zero_Loop ; / c094 18 03 c4 73 00 15 MOVW #Main_Menu,SCIBuf_Pointer ; Set the pointer to display the Main_Menu. c09a 16 c4 3d JSR Start_SCIDisp ; Start SCI0 interrupts rolling. c09d 16 c2 a4 JSR Get_Drive_ID c0a0 10 ef CLI ; Turn on interrupts and let the madness begin. Cycle: c0a2 20 fe BRA Cycle c0a4 cd 30 00 Large_Parse: LDY #Large_ASCII c0a7 ce 38 00 LDX #IDE_R_Buffer c0aa c7 CLRB c0ab a6 30 L_PARSE_LOOP: LDAA $01,X+ c0ad 16 c3 e3 JSR BIN_2_HEX c0b0 18 01 71 00 17 MOVW ASCII_BUF,$02,Y+ c0b5 18 08 70 20 MOVB #$20,$01,Y+ c0b9 52 INCB c0ba c1 10 CMPB #$10 c0bc 26 06 BNE NO_CR_YET c0be 18 00 71 0d 0a MOVW #$0D0A,$02,Y+ c0c3 c7 CLRB c0c4 8e 3a 00 NO_CR_YET: CPX #IDE_R_Buffer+512 c0c7 26 e2 BNE L_PARSE_LOOP c0c9 18 00 71 0d 0a MOVW #$0D0A,$02,Y+ c0ce 18 08 70 00 MOVB #$00,$01,Y+ c0d2 4d 13 02 BCLR Sys_Flags_0 #Out_Waiting c0d5 18 03 30 00 00 15 MOVW #Large_ASCII,SCIBuf_Pointer ; Set the pointer to display the Main_Menu. c0db 16 c4 3d JSR Start_SCIDisp ; Start SCI0 interrupts rolling. c0de 3d RTS *************************************************************************** * Interrupt Service Routines (Must be in top page of memory!!) * *************************************************************************** #include ADC_IRQ.asm ADC_IRQ: c0df 0b RTI #include SCI0_IRQ.asm c0e0 b6 08 c4 SCI0_IRQ: LDAA $08C4 ; SCI0 wants something... Let's determine what it is. c0e3 84 20 ANDA #$20 ; Does the transmitter have room for a new byte? c0e5 26 11 BNE SCI0_RECIEVE c0e7 de 15 LDX SCIBuf_Pointer ; Keep the bytes flowing to the SCI until we hit the null c0e9 a6 30 LDAA $01,X+ ; termination. At that point, we disable the transmitter's IRQ c0eb 27 06 BEQ SCI0BUFFEREND ; until we need more stuff sent. c0ed 7a 08 c7 STAA $08C7 c0f0 5e 15 STX SCIBuf_Pointer ; Re-store the incremented pointer. c0f2 0b RTI c0f3 1d 08 c3 80 SCI0BUFFEREND: BCLR $08C3 #$80 ; Disable transmitter interrupts. c0f7 0b RTI c0f8 b6 08 c7 SCI0_RECIEVE: LDAA $08C7 ; If the transmitter isn't talking, we can only assume it's c0fb 84 7f ANDA #$7F ; the receiver, so we grab a byte from the data register. c0fd 4e 14 01 6a BRSET SCI0_Flags #Getting_Input Aquire_Data c101 81 52 CMPA #82 ; If user presses R. c103 26 16 BNE SCI0_RECIEVE0 c105 18 03 c5 79 00 15 MOVW #EnterEff_ADR,SCIBuf_Pointer c10b 16 c4 3d JSR Start_SCIDisp c10e 4c 14 80 BSET SCI0_Flags #Reading_Value c111 4c 14 01 BSET SCI0_Flags #Getting_Input c114 18 0b 04 00 27 MOVB #$04,CharactersLeft c119 20 4f BRA SCI0_RECIEVEe c11b 81 57 SCI0_RECIEVE0: CMPA #87 ; If user presses W. c11d 26 16 BNE SCI0_RECIEVE1 c11f 18 03 c5 79 00 15 MOVW #EnterEff_ADR,SCIBuf_Pointer c125 16 c4 3d JSR Start_SCIDisp c128 4c 14 40 BSET SCI0_Flags #Writing_Value c12b 4c 14 01 BSET SCI0_Flags #Getting_Input c12e 18 0b 04 00 27 MOVB #$04,CharactersLeft c133 20 35 BRA SCI0_RECIEVEe c135 81 44 SCI0_RECIEVE1: CMPA #68 ; If user presses D. c137 26 16 BNE SCI0_RECIEVE2 c139 18 03 c5 79 00 15 MOVW #EnterEff_ADR,SCIBuf_Pointer c13f 16 c4 3d JSR Start_SCIDisp c142 4c 14 20 BSET SCI0_Flags #Dumping_Value c145 4c 14 01 BSET SCI0_Flags #Getting_Input c148 18 0b 04 00 27 MOVB #$04,CharactersLeft c14d 20 1b BRA SCI0_RECIEVEe c14f 81 5a SCI0_RECIEVE2: CMPA #90 ; If user presses Z. c151 26 05 BNE SCI0_RECIEVE3 c153 16 c0 a4 JSR Large_Parse c156 20 12 BRA SCI0_RECIEVEe c158 81 58 SCI0_RECIEVE3: CMPA #88 ; If user presses X. c15a 26 05 BNE SCI0_RECIEVE9 c15c 16 c0 a4 JSR Large_Parse c15f 20 09 BRA SCI0_RECIEVEe c161 18 03 c4 73 00 15 SCI0_RECIEVE9: MOVW #Main_Menu,SCIBuf_Pointer c167 16 c4 3d JSR Start_SCIDisp c16a 0b SCI0_RECIEVEe: RTI c16b 81 30 Aquire_Data: CMPA #$30 c16d 2d 2a BLT Error_InEntry c16f 81 46 CMPA #$46 c171 2e 26 BGT Error_InEntry c173 ce 00 23 LDX #UserInput_Buf ; Get the next position in the buffer, and store the value there. c176 c6 04 LDAB #$04 c178 d0 27 SUBB CharactersLeft c17a 1a e5 ABX c17c 6a 00 STAA $00,X c17e 73 00 27 DEC CharactersLeft c181 d6 27 LDAB CharactersLeft c183 26 13 BNE AQUIREDATAEND c185 4d 14 01 BCLR SCI0_Flags #Getting_Input c188 4e 14 02 68 BRSET SCI0_Flags #Input_Taken Write_Byte c18c 4e 14 20 34 BRSET SCI0_Flags #Dumping_Value Return_Lots c190 4e 14 80 0f BRSET SCI0_Flags #Reading_Value Return_Byte c194 4e 14 40 69 BRSET SCI0_Flags #Writing_Value GET_VALUE c198 0b AQUIREDATAEND: RTI c199 18 03 c5 99 00 15 Error_InEntry: MOVW #Enter_A_Hex,SCIBuf_Pointer c19f 16 c4 3d JSR Start_SCIDisp c1a2 0b RTI c1a3 07 73 Return_Byte: BSR HEX_2_ADDRESS c1a5 de 28 LDX Effective_ADR c1a7 a6 00 LDAA $00,X c1a9 16 c3 e3 JSR BIN_2_HEX c1ac 18 03 0d 0a 00 19 MOVW #$0D0A,ASCII_BUF+2 c1b2 18 0b 00 00 1b MOVB #$00,ASCII_BUF+4 c1b7 18 03 00 17 00 15 MOVW #ASCII_BUF,SCIBuf_Pointer c1bd 16 c4 3d JSR Start_SCIDisp c1c0 79 00 14 CLR SCI0_Flags c1c3 0b RTI c1c4 07 52 Return_Lots: BSR HEX_2_ADDRESS c1c6 de 28 LDX Effective_ADR c1c8 cd 30 00 LDY #Large_ASCII c1cb c6 10 LDAB #$10 c1cd a6 30 RLOTS_LOOP: LDAA $01,X+ c1cf 16 c3 e3 JSR BIN_2_HEX c1d2 18 01 71 00 17 MOVW ASCII_BUF,$02,Y+ c1d7 18 08 70 20 MOVB #$20,$01,Y+ c1db 04 31 ef DBNE B,RLOTS_LOOP c1de 18 00 71 0d 0a MOVW #$0D0A,$02,Y+ c1e3 18 08 70 00 MOVB #$00,$01,Y+ c1e7 18 03 30 00 00 15 MOVW #Large_ASCII,SCIBuf_Pointer c1ed 16 c4 3d JSR Start_SCIDisp c1f0 79 00 14 CLR SCI0_Flags c1f3 0b RTI c1f4 dc 25 Write_Byte: LDD UserInput_Buf+2 c1f6 16 c4 22 JSR HEX_2_BIN c1f9 de 28 LDX Effective_ADR c1fb 6a 00 STAA $00,X c1fd 79 00 14 CLR SCI0_Flags c200 0b RTI c201 07 15 GET_VALUE: BSR HEX_2_ADDRESS c203 4c 14 01 BSET SCI0_Flags #Getting_Input c206 18 0b 02 00 27 MOVB #$02,CharactersLeft c20b 18 03 c5 65 00 15 MOVW #Enter_DataMSG,SCIBuf_Pointer c211 16 c4 3d JSR Start_SCIDisp c214 4c 14 02 BSET SCI0_Flags #Input_Taken c217 0b RTI c218 dc 23 HEX_2_ADDRESS: LDD UserInput_Buf+0 c21a 16 c4 22 JSR HEX_2_BIN c21d 36 PSHA c21e dc 25 LDD UserInput_Buf+2 c220 16 c4 22 JSR HEX_2_BIN c223 18 0e TAB c225 32 PULA c226 5c 28 STD Effective_ADR c228 3d RTS #include SCI1_IRQ.asm c229 b6 08 cc SCI1_IRQ: LDAA $08CC c22c 0b RTI #include Unused_IRQ.asm c22d 18 0b 01 08 ae WakeUp_H: MOVB #$01,$08AE c232 20 f9 BRA WakeUp_H c234 18 0b 02 08 ae WakeUp_J: MOVB #$02,$08AE c239 20 f9 BRA WakeUp_J c23b 20 fe SPI_IRQ: BRA SPI_IRQ c23d 20 fe PAC_Edge: BRA PAC_Edge c23f 20 fe PAC_Over: BRA PAC_Over c241 20 fe Timer_OF: BRA Timer_OF c243 20 fe Timer_7: BRA Timer_7 c245 20 fe Timer_6: BRA Timer_6 c247 20 fe Timer_5: BRA Timer_5 c249 20 fe Timer_4: BRA Timer_4 c24b 20 fe Timer_3: BRA Timer_3 c24d 20 fe Timer_2: BRA Timer_2 c24f 20 fe Timer_1: BRA Timer_1 c251 20 fe Timer_0: BRA Timer_0 c253 20 fe RTI_IRQ: BRA RTI_IRQ c255 20 fe XIRQ_Pin: BRA XIRQ_Pin c257 0b Soft_IRQ: RTI c258 20 fe Reserved: BRA Reserved c25a 20 fe COP_RST: BRA COP_RST c25c 20 fe CMF_RST: BRA CMF_RST c25e 0b IRQ_Pin: RTI *************************************************************************** * Support Subroutines start here. * *************************************************************************** c25f 35 Delay: PSHY c260 cd 20 00 LDY #$2000 c263 04 36 fd DelayY: DBNE Y,DelayY c266 31 PULY c267 3d RTS c268 36 IDE_R_Data: PSHA c269 37 PSHB c26a 34 PSHX c26b b6 0b 8e LDAA IDE_AltStatus c26e 81 7f CMPA #$7F c270 2e 2d BGT END_R_DATA c272 18 0e TAB c274 c4 01 ANDB #$01 c276 26 03 BNE NO_R_ERRORS c278 16 c2 a3 JSR Report_Errors c27b 18 0e NO_R_ERRORS: TAB c27d c4 08 ANDB #$08 c27f 27 1e BEQ END_R_DATA c281 de 04 LDX Read_Pointer c283 79 00 06 CLR Bytes_Moved+0 c286 79 00 07 CLR Bytes_Moved+1 c289 18 09 30 0b 80 IDE_READ_LOOP: MOVB IDE_Data_Lo,1,X+ c28e 18 09 30 0b 90 MOVB IDE_Data_Hi,1,X+ c293 c3 00 02 ADDD #$0002 c296 b6 0b 8e LDAA IDE_AltStatus c299 84 08 ANDA #$08 c29b 26 ec BNE IDE_READ_LOOP c29d 5c 06 STD Bytes_Moved c29f 30 END_R_DATA: PULX c2a0 33 PULB c2a1 32 PULA c2a2 3d RTS c2a3 3d Report_Errors: RTS c2a4 b6 0b 8e Get_Drive_ID: LDAA IDE_AltStatus c2a7 84 40 ANDA #$40 c2a9 18 27 00 86 LBEQ DRV_NOT_READY c2ad 18 0b ec 0b 87 MOVB #$EC,IDE_Status ; Issue a drive ID command. c2b2 18 03 38 00 00 04 MOVW #IDE_R_Buffer,Read_Pointer c2b8 16 c2 5f JSR Delay c2bb 16 c2 5f JSR Delay c2be 16 c2 68 JSR IDE_R_Data c2c1 cd 30 00 LDY #Large_ASCII ; \ Put some text in the ASCII Buffer. c2c4 ce c5 ba LDX #Hard_Disk_NFO ; | c2c7 16 c3 34 JSR String_Concat ; / c2ca fc 38 0c LDD IDE_R_Buffer+12 ; Sectors-per-track is here. c2cd b7 81 EXG A,B ; Correct for endian-mismatch. c2cf 3b PSHD ; \ This is the setup and execution of the c2d0 fc 38 06 LDD IDE_R_Buffer+6 ; | MULU_16_16 sub. Here, we are multiplying c2d3 b7 81 EXG A,B ; | heads * sectors. Note, that we don't care c2d5 3b PSHD ; | about the MSW of the result, so we PULD c2d6 16 c4 42 JSR MULU_16_16 ; | and then ignore it. Don't pull the LSW off c2d9 3a PULD ; / the stack, we're about to use it. c2da fc 38 02 LDD IDE_R_Buffer+2 ; \ Here is the second multiplication operation. c2dd b7 81 EXG A,B ; | This is Cylinders * (Sectors * Heads). Note c2df 3b PSHD ; | that I only pushed one operand onto the stack. c2e0 16 c4 42 JSR MULU_16_16 ; | After this call, the 32-bit number in RESULT c2e3 3a PULD ; / will be the size of the drive in sectors. c2e4 7c 58 00 STD Total_Sectors+0 c2e7 5c 0f STD RESULT+0 c2e9 3a PULD c2ea 7c 58 02 STD Total_Sectors+2 c2ed 5c 11 STD RESULT+2 c2ef b6 58 00 LDAA Total_Sectors+0 ; We could RTS here if we didn't want things displayed. c2f2 16 c3 7f JSR HEX_2_BCD ; Convert the number in RESULT into BCD. c2f5 16 c3 64 JSR Bytes_2_Text ; Then ASCII format it, and put the result in ASCII_BUF. c2f8 34 PSHX ; Save the contents of X. c2f9 ce 00 17 LDX #ASCII_BUF ; / Then copy the number we just made into c2fc 16 c3 34 JSR String_Concat ; \ the big text buffer. c2ff ce c5 d0 LDX #Text_Sectors c302 16 c3 34 JSR String_Concat c305 ce c5 db LDX #Text_IDEModel c308 16 c3 34 JSR String_Concat c30b 37 PSHB c30c c6 14 LDAB #20 c30e ce 38 36 LDX #IDE_R_Buffer+54 ; Start of the Model number. c311 37 DMT_CONV_LOOP: PSHB c312 ec 31 LDD $02,X+ c314 b7 81 EXG A,B c316 6c 71 STD $02,Y+ c318 33 PULB c319 04 31 f5 DBNE B,DMT_CONV_LOOP c31c 33 PULB c31d 18 00 71 0d 0a MOVW #$0D0A,$02,Y+ c322 18 00 71 0d 0a MOVW #$0D0A,$02,Y+ c327 69 70 CLR $01,Y+ ; Null-terminate Large_ASCII c329 30 PULX c32a 18 03 30 00 00 15 MOVW #Large_ASCII,SCIBuf_Pointer c330 16 c4 3d JSR Start_SCIDisp c333 3d DRV_NOT_READY: RTS #include Number_Conversions.asm c334 a6 30 String_Concat: LDAA $01,X+ ; Use with care. Passed two pointers: X points to the null-term c336 27 04 BEQ END_SCONCAT ; string to copy, and Y points to the first byte the string is c338 6a 70 STAA $01,Y+ ; to be copied to. c33a 20 f8 BRA String_Concat c33c 3d END_SCONCAT: RTS c33d 34 HEX_2_DEC: PSHX ; This was taken from the HC11 manual. The division opcodes have been c33e 3b PSHD ; really supercharged for CPU12, so this sub executes very fast now. c33f ce 00 64 LDX #100 c342 18 10 IDIV c344 b7 c5 XGDX c346 cb 30 ADDB #$30 c348 5b 17 STAB ASCII_BUF c34a b7 c5 XGDX c34c ce 00 0a LDX #10 c34f 18 10 IDIV c351 b7 c5 XGDX c353 cb 30 ADDB #$30 c355 5b 18 STAB ASCII_BUF+1 c357 b7 c5 XGDX c359 cb 30 ADDB #$30 c35b 5b 19 STAB ASCII_BUF+2 c35d c6 20 LDAB #$20 c35f 5b 1a STAB ASCII_BUF+3 c361 3a PULD c362 30 PULX c363 3d RTS c364 36 Bytes_2_Text: PSHA ; Bytes_2_Text takes no parameter. It just converts the c365 34 PSHX ; field Bytes into a null-terminated ASCII string that c366 35 PSHY ; gets placed in ASCII_VAL. c367 ce 00 09 LDX #Bytes c36a cd 00 17 LDY #ASCII_BUF c36d a6 30 BYTES2TEXTLOO: LDAA $01,X+ c36f 16 c4 05 JSR BIN_2_HEX_IDX c372 8e 00 0e CPX #Bytes+5 c375 26 f6 BNE BYTES2TEXTLOO c377 18 08 70 00 MOVB #$00,$01,Y+ c37b 31 PULY c37c 30 PULX c37d 32 PULA c37e 3d RTS c37f 34 HEX_2_BCD: PSHX ; CalculateV is spliced right into HEX_2_BCD. First, save all c380 36 PSHA ; the registers and accumulators that are going to be used. c381 37 PSHB ; The word length for all of the conversions in this program c382 86 20 LDAA #WordLength ; are going to be 32-bit, and consequently the number of bytes c384 5a 0e STAA BitCount ; that will be returned will always be 5. Remember, packed BCD c386 ce 00 00 LDX #$0000 ; has two numbers per byte. Clear X and use it to do some c389 5e 09 STX Bytes ; housekeeping. We really should clear the output bytes before c38b 5e 0b STX Bytes+2 ; shifting them around. The BIN_2_BCD routine isn't completly c38d 5e 0c STX Bytes+3 ; my work. I used the algorithm from a Cyprus Semiconductor c38f 75 00 12 BIT_ROT_RESUM: ROL RESULT+3 ; application note. the original code was written for 8-bit c392 75 00 11 ROL RESULT+2 ; words and a different processor, so I *did* have to port and c395 75 00 10 ROL RESULT+1 ; extend it, but still... I have included the App note in the c398 75 00 0f ROL RESULT ; same directory as this listing. c39b 75 00 0d ROL Bytes+4 ; The ROtate Left instruction loads the LSB from the C-bit in c39e 75 00 0c ROL Bytes+3 ; the condition code register, and moves the old MSB from the c3a1 75 00 0b ROL Bytes+2 ; operand into the C-bit. Essentially a 9-bit rotation. This c3a4 75 00 0a ROL Bytes+1 ; is nice because we can extend the rotation to as many bytes c3a7 75 00 09 ROL Bytes ; as we want. In this case, 72-bits. Everytime we rotate once, c3aa 73 00 0e DEC BitCount ; we DEC BitCount and once we rotate 32 times, the conversion c3ad 26 04 BNE BIT_ROT_I_CHK ; is complete and we can exit. Restore all the registers and c3af 33 PULB ; return to the calling program. A really good algorithm. c3b0 32 PULA ; MUCH nicer then the nasty place division routine I was going c3b1 30 PULX ; to use. Really fast for arbitrarilly long words. My props to c3b2 3d RTS ; the guy who developed it. c3b3 86 05 BIT_ROT_I_CHK: LDAA #BytesOut ; Part of HEX_2_BCD. c3b5 5a 08 STAA ByteCount c3b7 07 02 BSR BIT_ROT_LSN_C c3b9 20 d4 BRA BIT_ROT_RESUM c3bb c6 09 BIT_ROT_LSN_C: LDAB #Bytes ; Another part of BIN_2_BCD. c3bd db 08 ADDB ByteCount c3bf 53 DECB c3c0 1a e5 ABX c3c2 a6 00 LDAA $00,X c3c4 18 0e TAB c3c6 c4 0f ANDB #$0F c3c8 c1 05 CMPB #$05 c3ca 25 04 BLO BIT_ROT_MAX_C c3cc 8b 03 ADDA #$03 c3ce 6a 00 STAA $00,X c3d0 a6 00 BIT_ROT_MAX_C: LDAA $00,X c3d2 81 50 CMPA #$50 c3d4 25 04 BLO END_BIT_ROT c3d6 8b 30 ADDA #$30 c3d8 6a 00 STAA $00,X c3da ce 00 00 END_BIT_ROT: LDX #$0000 c3dd 73 00 08 DEC ByteCount c3e0 26 d9 BNE BIT_ROT_LSN_C c3e2 3d RTS c3e3 36 BIN_2_HEX: PSHA ; Convert the value in AccA into A hex representation c3e4 44 LSRA ; and store it in ASCII_BUF c3e5 44 LSRA c3e6 44 LSRA c3e7 44 LSRA c3e8 81 09 CMPA #$09 c3ea 2f 02 BLE NOT_HEX_DIG0 c3ec 8b 07 ADDA #$07 c3ee 8b 30 NOT_HEX_DIG0: ADDA #$30 c3f0 5a 17 STAA ASCII_BUF c3f2 32 PULA c3f3 84 0f ANDA #$0F c3f5 81 09 CMPA #$09 c3f7 2f 02 BLE NOT_HEX_DIG1 c3f9 8b 07 ADDA #$07 c3fb 8b 30 NOT_HEX_DIG1: ADDA #$30 c3fd 5a 18 STAA ASCII_BUF+1 c3ff 18 0b 00 00 19 MOVB #$00,ASCII_BUF+2 c404 3d RTS c405 36 BIN_2_HEX_IDX: PSHA ; Convert the value in AccA into A hex representation c406 44 LSRA ; and store it in a location pointed to by Y. c407 44 LSRA c408 44 LSRA c409 44 LSRA c40a 81 09 CMPA #$09 c40c 2f 02 BLE NOT_IEX_DIG0 c40e 8b 07 ADDA #$07 c410 8b 30 NOT_IEX_DIG0: ADDA #$30 c412 6a 70 STAA $01,Y+ c414 32 PULA c415 84 0f ANDA #$0F c417 81 09 CMPA #$09 c419 2f 02 BLE NOT_IEX_DIG1 c41b 8b 07 ADDA #$07 c41d 8b 30 NOT_IEX_DIG1: ADDA #$30 c41f 6a 70 STAA $01,Y+ c421 3d RTS c422 16 c4 34 HEX_2_BIN: JSR EXPND_HEX_DIG ; Pass two ASCII vals in D, and the converted number c425 48 LSLA ; will be returned in AccA. c426 48 LSLA c427 48 LSLA c428 48 LSLA c429 36 PSHA c42a 18 0f TBA c42c 07 06 BSR EXPND_HEX_DIG c42e 18 0e TAB c430 32 PULA c431 18 06 ABA c433 3d RTS c434 80 30 EXPND_HEX_DIG: SUBA #$30 c436 81 09 CMPA #$09 c438 2f 02 BLE NXT_HEX_VAL c43a 80 07 SUBA #$07 c43c 3d NXT_HEX_VAL: RTS c43d 1c 08 c3 80 Start_SCIDisp: BSET $08C3 #$80 ; Enable SCI0's transmitter related interrupts. c441 3d RTS #include math.asm **************************************************************** * This library is used to extend the HC12's math capabilities * **************************************************************** c442 3b MULU_16_16: PSHD ; The HC11 has an 8-bit CPU, and so cannot deal with 16-bit c443 3b PSHD ; multiplication. MULU_16_16 takes two 16-bit numbers and c444 a6 89 LDAA $09,SP ; multiplies them together, placing the 32-bit result in c446 e6 87 LDAB $07,SP ; the stack space where the two operands once occupied. c448 12 MUL ; This routine doesn't need any static variables, but it c449 6c 82 STD $02,SP ; does use 10 bytes of stack space, including the call to c44b a6 89 LDAA $09,SP ; the sub, and all parameter passing. A call to this sub c44d e6 86 LDAB $06,SP ; would look like this: c44f 12 MUL ; LDD Operand1 ; I used D to illustrate, but this should c450 eb 82 ADDB $02,SP ; PSHD ; also work using an index register, or a c452 89 00 ADCA #0 ; LDD Operand2 ; MOVW instruction. Placing values on the c454 6c 81 STD $01,SP ; PSHD ; stack before the call is passing factors. c456 a6 88 LDAA $08,SP ; JSR MULU_16_16 ; Call the sub. c458 e6 87 LDAB $07,SP ; PULD ; Most significant word of product. c45a 12 MUL ; PULD ; Least significant word of product. c45b eb 82 ADDB $02,SP c45d a9 81 ADCA $01,SP ; READ THIS DAMMIT! You MUST re-adjust the stack after calling c45f 6c 81 STD $01,SP ; MULU_16_16 even if you aren't interested in the result. c461 a6 88 LDAA $08,SP ; What's more, you MUST PLACE four bytes on the stack before c463 e6 86 LDAB $06,SP ; calling MULU_16_16. If you do not do either of these things, c465 12 MUL ; your program will get a nice surprise when you try to RTS c466 eb 81 ADDB $01,SP ; next. Remember, this function modifies values on the stack c468 89 00 ADCA #0 ; that were placed there BEFORE the return address from the JSR c46a 6c 80 STD $00,SP ; that called it. c46c 3a PULD ; Destroy the stack space we created at the beginning of this c46d 6c 84 STD $04,SP ; sub. c46f 3a PULD c470 6c 84 STD $04,SP c472 3d RTS *************************************************************************** * Constants start here. * *************************************************************************** c473 0d 0a Main_Menu: FDB $0D0A c475 43 6f 6e 74 72 6f FCC 'Controller Main Menu:' 6c 6c 65 72 20 4d 61 69 6e 20 4d 65 6e 75 3a c48a 0d 0a FDB $0D0A c48c 2d 2d 2d 2d 2d 2d FCC '----------------------------' 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d c4a8 0d 0a FDB $0D0A c4aa 57 3e 20 4d 6f 64 FCC 'W> Modify memory value' 69 66 79 20 6d 65 6d 6f 72 79 20 76 61 6c 75 65 c4c0 0d 0a FDB $0D0A c4c2 52 3e 20 52 65 61 FCC 'R> Read a memory value' 64 20 61 20 6d 65 6d 6f 72 79 20 76 61 6c 75 65 c4d8 0d 0a FDB $0D0A c4da 44 3e 20 44 75 6d FCC 'D> Dump 16 bytes' 70 20 31 36 20 62 79 74 65 73 c4ea 0d 0a FDB $0D0A c4ec 58 3e 20 52 65 63 FCC 'X> Recieve 1,000,000 bytes from SCI to HDD' 69 65 76 65 20 31 2c 30 30 30 2c 30 30 30 20 62 79 74 65 73 20 66 72 6f 6d 20 53 43 49 20 74 6f 20 48 44 44 c516 0d 0a FDB $0D0A c518 59 3e 20 53 70 69 FCC 'Y> Spit 1,000,000 bytes from HDD to SPI' 74 20 31 2c 30 30 30 2c 30 30 30 20 62 79 74 65 73 20 66 72 6f 6d 20 48 44 44 20 74 6f 20 53 50 49 c53f 0d 0a FDB $0D0A c541 5a 3e 20 44 75 6d FCC 'Z> Dump 512 bytes of IDE_R_Buffer' 70 20 35 31 32 20 62 79 74 65 73 20 6f 66 20 49 44 45 5f 52 5f 42 75 66 66 65 72 c562 0d 0a FDB $0D0A c564 00 FCB $00 c565 45 6e 74 65 72 20 Enter_DataMSG: FCC 'Enter the value: ' 74 68 65 20 76 61 6c 75 65 3a 20 c576 0d 0a FDB $0D0A c578 00 FCB $00 c579 45 6e 74 65 72 20 EnterEff_ADR: FCC 'Enter the effective address: ' 74 68 65 20 65 66 66 65 63 74 69 76 65 20 61 64 64 72 65 73 73 3a 20 c596 0d 0a FDB $0D0A c598 00 FCB $00 c599 56 61 6c 75 65 73 Enter_A_Hex: FCC 'Values must be entered in hex.' 20 6d 75 73 74 20 62 65 20 65 6e 74 65 72 65 64 20 69 6e 20 68 65 78 2e c5b7 0d 0a FDB $0D0A c5b9 00 FCB $00 c5ba 48 61 72 64 20 64 Hard_Disk_NFO: FCC 'Hard drive summary:' 72 69 76 65 20 73 75 6d 6d 61 72 79 3a c5cd 0d 0a FDB $0D0A c5cf 00 FCB $00 c5d0 20 73 65 63 74 6f Text_Sectors: FCC ' sectors' 72 73 c5d8 0d 0a FDB $0D0A c5da 00 FCB $00 c5db 44 72 69 76 65 20 Text_IDEModel: FCC 'Drive identifies itself as a ' 69 64 65 6e 74 69 66 69 65 73 20 69 74 73 65 6c 66 20 61 73 20 61 20 c5f8 00 FCB $00 *************************************************************************** * Interrupt vectors are defined here. (All ISRs must be in top page!!) * *************************************************************************** 0835 ORG $0835 ; Set PPAGE register to the last page of the 512K EEPROM. 0835 1f FCB #$1F bfce ORG $BFCE ; This is what the MCU will see as the vector space. bfce c2 2d FDB WakeUp_H ;KEY WAKEUP H bfd0 c2 34 FDB WakeUp_J ;KEY WAKEUP J bfd2 c0 df FDB ADC_IRQ ;ANALOG TO DIGITAL bfd4 c2 29 FDB SCI1_IRQ ;SERIAL COMMUNICATION 1 bfd6 c0 e0 FDB SCI0_IRQ ;SERIAL COMMUNICATION 0 bfd8 c2 3b FDB SPI_IRQ ;SPI SERIAL TRANSFER COMPLETE bfda c2 3d FDB PAC_Edge ;PULSE ACCUMULATOR INPUT EDGE bfdc c2 3f FDB PAC_Over ;PULSE ACCUMULATOR OVERFLOW bfde c2 41 FDB Timer_OF ;TIMER OVERFLOW bfe0 c2 43 FDB Timer_7 ;TIMER CHANNEL 7 bfe2 c2 45 FDB Timer_6 ;TIMER CHANNEL 6 bfe4 c2 47 FDB Timer_5 ;TIMER CHANNEL 5 bfe6 c2 49 FDB Timer_4 ;TIMER CHANNEL 4 bfe8 c2 4b FDB Timer_3 ;TIMER CHANNEL 3 bfea c2 4d FDB Timer_2 ;TIMER CHANNEL 2 bfec c2 4f FDB Timer_1 ;TIMER CHANNEL 1 bfee c2 51 FDB Timer_0 ;TIMER CHANNEL 0 bff0 c2 53 FDB RTI_IRQ ;REAL TIME INTERRUPT bff2 c2 5e FDB IRQ_Pin ;IRQ OR KEY WAKE UP D bff4 c2 55 FDB XIRQ_Pin ;XIRQ bff6 c2 57 FDB Soft_IRQ ;SWI bff8 c2 58 FDB Reserved ;RESERVED bffa c2 5a FDB COP_RST ;COP FAILURE RESET bffc c2 5c FDB CMF_RST ;COP CLOCK MONITOR FAIL RESET bffe c0 00 FDB RESET ;RESET Total errors: 0 Total warnings: 0