From af53063ac3d33ad02d5b991392da63aaba5f6e32 Mon Sep 17 00:00:00 2001 From: Werner Johansson Date: Wed, 19 Feb 2003 17:37:48 -0800 Subject: [PATCH] Initial v0.0 commit Signed-off-by: Werner Johansson --- wj-uni.asm | 824 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 824 insertions(+), 0 deletions(-) create mode 100644 wj-uni.asm diff --git a/wj-uni.asm b/wj-uni.asm new file mode 100644 index 0000000..ecb6d6a --- /dev/null +++ b/wj-uni.asm @@ -0,0 +1,824 @@ + title "PIC16F870 Unilink Interface by Werner Johansson (c) 2003" + subtitl "Definitions" + list c=132,P=16F870,R=DEC,F=inhx8m + include "p16f870.inc" ; Standard equates & Macros + ERRORLEVEL 1,-302 ; Get rid of those annoying 302 msgs! + + +;---------------------------------------------------------------- +; The Configuration Word + __CONFIG _HS_OSC&_WDT_OFF&_PWRTE_ON&_BODEN_ON&_LVP_OFF&_CPD_OFF&_WRT_ENABLE_ON&_DEBUG_OFF&_CP_OFF + +;---------------------------------------------------------------- +; HISTORY +;---------------------------------------------------------------- +; Version +; +; 0.0 Very first "Fucking No Work!" version +; +;---------------------------------------------------------------- + +; Unilink BUSON IN (blue) connected to RC2/CCP1 +; Unilink DATA (green) connected to RC3 +; Unilink BUSON OUT (blue) connected to RC4 (this is for daisy-chaining) +; Unilink CLK (yellow) connected to RB0/INT (Interrupt pin) +; Unilink RST (lilac) connected to RA4 +; LCD RS connected to pin RB1 +; LCD RW connected to pin RB2 +; LCD E connected to pin RB3 +; LCD DB4-DB7 connected to RB4-RB7 +; RS-232 TX from computer connected to RC7/RX +; RS-232 RX to computer connected to RC6/TX +; RS-232 RI to computer connected to RC5 + +; This leaves RC0, RC1 and the analog inputs (AN0-AN4) free for now... + +#define LCD_RS_BIT PORTB,1 +#define LCD_RW_BIT PORTB,2 +#define LCD_E_BIT PORTB,3 +#define LCD_DB4_BIT PORTB,4 +#define LCD_DB5_BIT PORTB,5 +#define LCD_DB6_BIT PORTB,6 +#define LCD_DB7_BIT PORTB,7 + +;---------------------------------------------------------------- +; File register usage + +Dcount equ 20h +e_LEN equ 21h +Icount equ 2Dh ; Offset of string to print +TxTemp equ 2Eh ; blahblah +TxTemp2 equ 2Fh ; Blahblah2 + +LCDWTmp equ 30h +Dcount2 equ 31h +temp equ 32h + +DataCount equ 33h +DataStore equ 34h + +IRQW equ 7fh +IRQSTATUS equ 7eh +IRQPCLATH equ 7dh + + subtitl "Startup" + page +;---------------------------------------------------------------- +; Power up/Reset starting point [den rulerar] + + org 0 + call Bootstrap ; Call Flash Load routine + call LCDInit ; Initialize LCD I/F + call IRQInit ; Set up and start the IRQ handler + goto Main ; Run the main program loop (skip the IRQ handler) + + subtitl "IRQ Handler" +;---------------------------------------------------------------- +; Interrupt handler always starts at addr 4 + + org 4 ; Must be on Address 4! + movwf IRQW ; Save W + swapf STATUS,w ; Get the status register into w + clrf STATUS ; Zero out the status reg, gives us Bank0 all the time + movwf IRQSTATUS + movf PCLATH,w + movwf IRQPCLATH + clrf PCLATH + + btfss INTCON,INTF ; Check if it's INT (CLK) + goto IRQNotINT ; Nope + + movlw 8 ; Loop this many times + movwf DataCount + +CLKWaitHigh + btfsc PORTA,4 ; Check for RST + goto IRQAfterINT + btfss PORTC,2 ; Check for BUSON + goto IRQAfterINT + btfss PORTB,0 ; Wait for clock to go high + goto CLKWaitHigh +CLKWaitLow + btfsc PORTA,4 ; Check for RST + goto IRQAfterINT + btfss PORTC,2 ; Check for BUSON + goto IRQAfterINT + btfsc PORTB,0 ; Wait for clock to go low + goto CLKWaitLow + + clrc ; Clear carry + btfss PORTC,3 ; Test DATA + setc ; Set carry if data is LOW (data is inverted!) + rlf DataStore,f ; Shift it into our accumulator + + decfsz DataCount,f ; Loop once more perhaps? + goto CLKWaitHigh + +IRQAfterINT + + bcf INTCON,INTF ; Clear our IRQ + +IRQNotINT + + movf IRQPCLATH,w + movwf PCLATH ; Restore PCLATH + swapf IRQSTATUS,w + movwf STATUS ; Restore STATUS + swapf IRQW,f + swapf IRQW,w ; Restore W + retfie ; Interrupt return + + + + subtitl "Main loop" + page + +;---------------------------------------------------------------- +; Data can be stored between here and 100h... + +StartUpText1 + DT "-WJ UniLink I/F-" +StartUpText2 + DT "Code and design:" +StartUpText3 + DT "**TCC of Yodel**" + + +LookUp movwf PCL ; Go to it + +;---------------------------------------------------------------- +; Main program begins here. [Called after bootloader, lcdinit and irqinit...] + + org 100h +Main + + bsf STATUS,RP0 + bsf TXSTA,TXEN ; Enable UART TX + bcf STATUS,RP0 ; Back to bank 0 + + bsf RCSTA,SPEN ; Enable serial port + bsf RCSTA,CREN ; Enable UART RX + +retry + +; movlw 8 ; Loop this many times +; movwf DataCount + +;CLKWaitHigh +; btfsc PORTA,4 ; Check for RST +; goto retry +; btfss PORTC,2 ; Check for BUSON +; goto retry +; btfss PORTB,0 ; Wait for clock to go high +; goto CLKWaitHigh +;CLKWaitLow +; btfsc PORTA,4 ; Check for RST +; goto retry +; btfss PORTC,2 ; Check for BUSON +; goto retry +; btfsc PORTB,0 ; Wait for clock to go low +; goto CLKWaitLow + +; clrc ; Clear carry +; btfss PORTC,3 ; Test DATA +; setc ; Set carry if data is LOW (data is inverted!) +; rlf DataStore,f ; Shift it into our accumulator + +; decfsz DataCount,f ; Loop once more perhaps? +; goto CLKWaitHigh + + bcf LCD_RS_BIT ;Command mode + movlw 80h ;DisplayRam 0 + call TxLCDB + bsf LCD_RS_BIT + + movlw '0' + btfsc PORTA,4 ; Test RST + movlw 'R' + call TxLCDB + + movlw '0' + btfsc PORTB,0 ; Test CLK + movlw 'C' + call TxLCDB + + movlw '0' + btfsc PORTC,2 ; Test BUSON-IN + movlw 'B' + call TxLCDB + + movlw '0' + btfsc PORTC,3 ; Test DATA + movlw 'D' + call TxLCDB + + movf DataCount,w ; Load bit counter (if 0 then byte is available) + skpz + goto retry + + movf DataStore,w ; Get the result + decf DataCount,f ; Set it non-zero + + call BootTXB ; Send to terminal + + goto retry + + + + movlw StartUpText1 + call TxLCD16B + call LongDelay + + bsf PORTA,4 ; turn off LED + + movlw StartUpText2 + call TxLCD16B + call LongDelay + + bcf PORTA,4 ; turn on LED + + movlw StartUpText3 + call TxLCD16B + call LongDelay + + goto retry + + +;---------------------------------------------------------------- +; IRQInit - Sets up the IRQ Handler + +IRQInit + bsf STATUS,RP0 ; Reg bank 1 +; bcf OPTION_REG,INTEDG ; We want RB0 to give us an IRQ on the falling edge + bsf INTCON,INTE ; Enable the RB0/INT + bsf INTCON,GIE ; Enable global interrupts + bcf STATUS,RP0 ; Back to bank 0 + return + +;---------------------------------------------------------------- +; Initialize LCD Controller... + +LCDInit + clrf PORTB + bsf STATUS,RP0 ; Hi Bank + movlw 0cfh ; RC4 & RC5 should be outputs... + movwf TRISC ; Yep. + movlw 001h ; All but RB0 are outputs. + movwf TRISB ; Yep + bcf OPTION_REG,NOT_RBPU ; Turn on port B pull-up + bcf STATUS,RP0 ; Restore Lo Bank + +; bcf PORTA,4 ; turn on LED + +; movlw 44 ; Should be 16ms delay + movlw 255 ; Should be 16ms delay + call DelayW + + movlw 3 ; Write 3 to the LCD + call TxLCD ; Send to LCD +; movlw 12 ; Should be 5ms delay + movlw 255 ; Should be 16ms delay + call DelayW + + movlw 3 ; Write 3 to the LCD + call TxLCD +; movlw 12 ; Should be 16ms delay + movlw 255 ; Should be 16ms delay + call DelayW + + movlw 3 ; Write 3 to the LCD + call TxLCD +; movlw 44 + movlw 255 ; Should be 16ms delay + call DelayW + + movlw 2 ;\ + call TxLCD ; | 4-bit interface +; movlw 55 ; | After this we are ready to ROCK! + movlw 255 ; Should be 16ms delay + call DelayW ;/ + +; bsf PORTA,4 ; turn off LED + + movlw 28h ; Some random commands :))) + call TxLCDB + + movlw 0ch ; hmmm + call TxLCDB + + movlw 01h ; hmmm + call TxLCDB + + movlw 06h ; hmmm + call TxLCDB + + return + +;---------------------------------------------------------------- +; LongDelay - Well, guess that for yourself... + +LongDelay +; btfss PORTB,6 ; Talk to da PC? +; goto PCTalk ; Oh yeah... + + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + movlw 255 + call DelayW + return + +;---------------------------------------------------------------- +; TxLCD16B +; Send a string to the LCD. + +TxLCD16B + movwf Icount + bcf LCD_RS_BIT + movlw 80h ;DisplayRam 0 + call TxLCDB + bsf LCD_RS_BIT + call TxLCD8B + bcf LCD_RS_BIT + movlw 80h+40 ;DisplayRam 40 (row 2) + call TxLCDB + bsf LCD_RS_BIT + call TxLCD8B + return + +;---------------------------------------------------------------- +; TxLCD8B +; Send a string to the LCD. + +TxLCD8B +; movwf Icount ; Icount = W + movlw 8 + movwf e_LEN ; Move to e_LEN + +Txm_lp movf Icount,w ; get the byte + call LookUp + incf Icount,f ; ...else ++Icount (table index) + call TxLCDB ; Send out the byte + decfsz e_LEN,f + goto Txm_lp + return + +;---------------------------------------------------------------- +; TxLCDB - send a byte to the LCD + +TxLCDB + movwf TxTemp ; Store byte to send for a while... + + bcf temp,0 ; Clear my temp bit + btfss LCD_RS_BIT ; Check if we try the correct reg + goto RxNoProb + bcf LCD_RS_BIT + bsf temp,0 ; Indicate RS change +RxNoProb + +NotReady + call RxLCDB ; Receive byte from LCD, status reg + andlw 80h + btfss STATUS,Z ; If the bit was set, the zero flag is not + goto NotReady + + btfsc temp,0 ; If we had to clear RS reset it now + bsf LCD_RS_BIT + + swapf TxTemp,w ; Hi nibble of data to send in lo w bits + call TxLCD ; Send them first... + movf TxTemp,w ; Then we have the low nibble in low w bits + call TxLCD ; And send that one as well + + return +;---------------------------------------------------------------- +; RxLCDB - recv a byte from the LCD + +RxLCDB + call RxLCD ; Receive the high nibble + movwf LCDWTmp + swapf LCDWTmp,f ; Swap it back to file + call RxLCD ; Receive the low nibble + addwf LCDWTmp,w ; Put the nibbles together and return in W + + return + +;---------------------------------------------------------------- +; TxLCD - send a nibble to the LCD + +TxLCD + movwf LCDWTmp ; Write nibble to tmp + bcf LCD_DB4_BIT ; Clear previous data + bcf LCD_DB5_BIT ; + bcf LCD_DB6_BIT ; + bcf LCD_DB7_BIT ; + + btfsc LCDWTmp,0 ; Test bit 0, transfer a set bit to LCD PORT + bsf LCD_DB4_BIT + btfsc LCDWTmp,1 ; Test bit 1, transfer a set bit to LCD PORT + bsf LCD_DB5_BIT + btfsc LCDWTmp,2 ; Test bit 2, transfer a set bit to LCD PORT + bsf LCD_DB6_BIT + btfsc LCDWTmp,3 ; Test bit 3, transfer a set bit to LCD PORT + bsf LCD_DB7_BIT + + bsf LCD_E_BIT ; And set E to clock the data into the LCD module + nop ; Let it settle + bcf LCD_E_BIT ; And clear the Enable again. + return ; Returns without modifying W + +;---------------------------------------------------------------- +; RxLCD - recv a nibble from the LCD + +RxLCD + clrw ; Clear W register, return data in lower 4 bits + + bsf STATUS,RP0 ; Select 2nd reg bank, now TRIS regs can be accessed + + bsf LCD_DB4_BIT ; This sets the port bit as an input + bsf LCD_DB5_BIT + bsf LCD_DB6_BIT + bsf LCD_DB7_BIT + bcf STATUS,RP0 ; Back at reg bank 0 + + bsf LCD_RW_BIT ; Set Read mode for the LCD + bsf LCD_E_BIT ; And set E to clock the data out of the LCD module + nop ; Let the bus settle + btfsc LCD_DB4_BIT ; Transfer a set port bit into W + addlw 1 + btfsc LCD_DB5_BIT ; Transfer a set port bit into W + addlw 2 + btfsc LCD_DB6_BIT ; Transfer a set port bit into W + addlw 4 + btfsc LCD_DB7_BIT ; Transfer a set port bit into W + addlw 8 + bcf LCD_E_BIT ; And clear the Enable again. + bcf LCD_RW_BIT ; Set Write mode for the LCD + + bsf STATUS,RP0 ; Select 2nd reg bank, now TRIS regs can be accessed + bcf LCD_DB4_BIT ; Set the port as an output again + bcf LCD_DB5_BIT ; + bcf LCD_DB6_BIT ; + bcf LCD_DB7_BIT ; + bcf STATUS,RP0 ; Back at reg bank 0 + + return ; Returns with data in W + +;---------------------------------------------------------------------- +; Delay routines (one iteration=3 cycles. That is 0.366211ms @32kHz) +; 2.73* # of ms is good... + +DelayW movwf Dcount ; Set delay counter + clrf Dcount2 + decf Dcount2,f +DelayLp decfsz Dcount,f + goto DelayIn + retlw 0 +DelayIn decfsz Dcount2,f + goto DelayIn2 + decf Dcount2,f + goto DelayLp +DelayIn2 goto $+1 + goto $+1 + goto $+1 + goto DelayIn + + subtitl "Bootstrap/Bootloader code" + page + +;---------------------------------------------------------------------- +; Bootstrap code - Allows PIC to flash itself with data from async port +; Startup @9600bps + + org 700h ; Place the boot code at the top of memory + +BootRXState equ 7fh ; What are we waiting for @RX +BootBits equ 7eh ; bit0 1=write 0=read, bit1 1=PGM 0=EE, bit2 0=normal 1=no-op when prog +BootAddrL equ 7dh +BootAddrH equ 7ch +BootDataL equ 7bh +BootDataH equ 7ah +BootTimerL equ 79h +BootTimerM equ 78h +BootTimerH equ 77h +BootNumBytes equ 76h +BootDataVL equ 75h +BootDataVH equ 74h +BootHEXTemp equ 73h +BootStrTemp equ 72h + +Bootstrap + movlw 7 + movwf PCLATH + + bsf STATUS,RP0 ; Access bank 1 + bsf TXSTA,TXEN ; Enable UART TX + movlw 31 ; Divisor for 9k6 @ 20MHz Fosc + movwf SPBRG ; Store + bcf STATUS,RP0 ; Back to bank 0 + + bsf RCSTA,SPEN ; Enable serial port + bsf RCSTA,CREN ; Enable UART RX + +; clrf BootRXState ; Waiting for command + + movlw BootStartText + call BootTXStr + + movlw 0e8h + movwf BootTimerL + movwf BootTimerM + movwf BootTimerH + +BootTimeout + incf BootTimerL,f ; A 24-bit counter + skpnz + incf BootTimerM,f + skpnz + incf BootTimerH,f + skpnz ; When overflowing here.. + goto BootReturn ; ..Exit boot loader, no keypress within timeout period, resume program + btfss PIR1,RCIF ; Wait for RX to complete + goto BootTimeout + call BootRXB + xorlw 27 ; ESC + btfss STATUS,Z + goto BootTimeout ; If it wasn't space, wait for another key + +BootFlash + movlw BootFlashText + call BootTXStr + + bsf BootBits,1 + clrf BootAddrL + clrf BootAddrH + +BootLoop + call BootRXB ; First find the ':' + xorlw ':' + skpz + goto BootLoop ; Loop until we find it! + + call BootRXHEX ; Get one ASCII encoded byte (two chars) + movwf BootNumBytes ; This is the number of bytes to be programmed on the line +; Maybe clear cary here? + rrf BootNumBytes,f ; Right shift because we're double addressing this 8-bit format + +; Note carry should be clear here as there cannot be odd number of bytes in this format + + call BootRXHEX ; Receive AddrH + movwf BootAddrH + call BootRXHEX ; Receive AddrL + movwf BootAddrL + rrf BootAddrH,f ; Fix the addressing again + rrf BootAddrL,f + + bcf BootBits,2 ; Assume we should program + bsf BootBits,1 ; And assume we should program flash not ee + + movf BootAddrH,w + xorlw 020h ; Check if it's configuration, which we can't program + skpnz ; Skip the bit set if it was false alarm + bsf BootBits,2 ; No programming for this line + + xorlw 001h ; Also check if it's EEPROM memory (first xor 20h then 1 =21h) + skpnz ; Skip the bit set instr if not EE data address + bcf BootBits,1 ; We should program EE, will ignore the AddrH + + call BootRXHEX ; Receive Record Type (must be 0 for real records) + skpz ; Check if zero + goto BootFlashComplete + +BootLineLoop + call BootRXHEX ; Receive low-byte of data word + movwf BootDataVL + call BootRXHEX ; Receive high-byte of data word + movwf BootDataVH + + btfsc BootBits,2 ; Check whether this line should be programmed at all + goto BootWriteSkip + + bcf BootBits,0 ; Read mode first, verify if we actually have to write + call BootEE + movf BootDataVL,w + xorwf BootDataL,f ; Compare and destroy DataL + movwf BootDataL ; Write new data to DataL + skpz ; Skip if no difference, have to check high byte as well + goto BootWrite ; Jump directly to write + + movf BootDataVH,w + xorwf BootDataH,f ; Compare + skpnz ; Skip if no difference, no programming necessary + goto BootWriteSkip + +BootWrite + movf BootDataVH,w + movwf BootDataH ; Have to put the new H byte data in as well + +; movlw '+' +; call BootTXB ; Send progword indicator + + bsf BootBits,0 + call BootEE ; Write directly into program mem + +; Here a verify can take place, the read-back results are now in DataL/H + + movlw '+' + goto BootWriteDone + +BootWriteSkip + movlw '-' +BootWriteDone + call BootTXB + + incf BootAddrL,f ; Advance counter to next addr + skpnz + incf BootAddrH,f ; And add to high byte if needed + + decfsz BootNumBytes,f + goto BootLineLoop + + movlw 13 ; Progress + call BootTXB + movlw 10 ; Progress + call BootTXB + + goto BootLoop + +BootFlashComplete + +BootReturn + movlw BootRunText + call BootTXStr + + bsf STATUS,RP0 +BootReturnWait + btfss TXSTA,TRMT ; Wait for last things to flush + goto BootReturnWait + bcf TXSTA,TXEN ; Disable UART TX + bcf STATUS,RP0 ; Back to bank 0 + + bcf RCSTA,SPEN ; Enable serial port + bcf RCSTA,CREN ; Enable UART RX + + clrf PCLATH + return ; Return to code + +;---------------------------------------------------------------------- +; BootTXB - Sends one byte to the UART, waits for transmitter to become +; free before sending + +BootTXB +BootTXW1 + btfss PIR1,TXIF ; Wait for TX to empty + goto BootTXW1 + movwf TXREG ; Send the byte + return + +;---------------------------------------------------------------------- +; BootTXStr - Sends ASCII string pointed to by W, zero terminated + +BootTXStr + movwf BootStrTemp ; Store offset + call BootLookup ; Lookup char + addlw 0 + skpnz + return + call BootTXB ; Send char + incf BootStrTemp,w ; Retrieve + goto BootTXStr + +;---------------------------------------------------------------------- +; BootRXB - Receives one byte from the UART, waits if nothing available + +BootRXB +BootRXW1 + btfss PIR1,RCIF ; Wait for RX to complete + goto BootRXW1 + movf RCREG,w ; Get the recvd byte + return + +;---------------------------------------------------------------------- +; BootRXHEXNibble - Receives one byte and converts it from ASCII HEX to binary + +BootRXHEXNibble + call BootRXB ; Receive nibble + + addlw -'A' ; Convert from BCD to binary nibble + skpc ; Test if if was 0-9 or A-F, skip if A-F + addlw 'A' - 10 - '0' ; It was numeric '0' + addlw 10 ; Add 10 (A get to be 0ah etc.) + return + +;---------------------------------------------------------------------- +; BootRXHEX - Receives two bytes from the UART, waits if nothing available +; Decodes the bytes as ASCII hex and returns a single byte in W + +BootRXHEX + call BootRXHEXNibble + movwf BootHEXTemp + swapf BootHEXTemp,f ; Swap it up to the high nibble + + call BootRXHEXNibble + addwf BootHEXTemp,w ; And add the two nibbles together + return + +;---------------------------------------------------------------------- +; BootEE - Reads or writes EE or Flash memory, BootBits specify the +; exact action to take. BootAddrL and BootAddrH has to be initialized +; to the address of choice (0000-003fh for EE and 0000h-07ffh for flash +; The data to be written has to be put in BootDataL and BootDataH, and +; data will be to the same place when read back + +BootEE + bsf STATUS,RP1 ; Select bank 2 (RP0 must be 0) + + movf BootAddrH,w ; Load desired address + movwf EEADRH + movf BootAddrL,w + movwf EEADR + movf BootDataH,w ; And load the data (only used when writing) + movwf EEDATH + movf BootDataL,w + movwf EEDATA + + bsf STATUS,RP0 ; Go to bank 3 + + bsf EECON1,EEPGD ; Point to Program Flash mem + btfss BootBits,1 ; Test if that was correct or if we have to clear again + bcf EECON1,EEPGD ; Point to EE DATA mem + + btfss BootBits,0 ; Check from read or write + goto BootEERD ; Skip the WR if we were going for a read + + bsf EECON1,WREN ; Enable writes + movlw 55h + movwf EECON2 + movlw 0AAh + movwf EECON2 ; Unlock write operation + bsf EECON1,WR ; And start a write cycle +BootWRLoop + btfsc EECON1,WR ; This executes for EE only not flash, waits for WR to finish + goto BootWRLoop ; These two instructions gets NOPed when flashing + + bcf EECON1,WREN ; Finally disable writes again + ; Here we read the data back again, can be used as verify +BootEERD + bsf EECON1,RD ; Start a read cycle + nop ; Only necessary for flash read, same thing as when writing above + nop ; Except I could use the two words for something useful there.. :) + +BootEEX + bcf STATUS,RP0 ; Back to bank 2 + movf EEDATA,w ; Store our EE-data + movwf BootDataL + movf EEDATH,w + movwf BootDataH + bcf STATUS,RP1 ; And finally back to bank 0 + + return + +BootStartText + DT "WJBoot - press ESC to flash",0 +BootFlashText + DT 13,10,"Send INHX8 file now...",13,10,0 +BootRunText + DT 13,10,"Exiting loader",13,10,0 + +BootLookup + movwf PCL ; Go fetch the char data + +;---------------------------------------------------------------------- +; EE Data (64 bytes), located at 2100h + + org 2100h +; data 0f2h, 099h, 000h, 000h, 018h, 0a5h, 090h, 084h + + END -- 1.7.3