; EOHCountdown.asm ; By Joel Jordan ; SigArch, ACM@UIUC ; http://www.acm.uiuc.edu/sigarch/ ; 1/19/04 ; Counts days, hours, minutes, seconds until EOH ; Generates NTSC video signal in software ; uses PIC Breakout circuit, PIC16F84 @ 12MHz ; This generates non-interlaced NTSC video, ~61 frames per second, ; 256 horizontal lines per frame. Each horizontal scanline is ; 64 microseconds long, each frame is 16384 microseconds. ; Two buttons are used to set the countdown interval. To set, ; use the POS_BUTTON to select a field to edit, use the SET_BUTTON ; to increment the value. The countdown will begin when you've ; cycled through all of the fields with the POS_BUTTON. #include "p16f84.inc" LIST P=16F84, R=HEX __CONFIG _WDT_OFF & _XT_OSC & _CP_OFF #define SYNC PORTA, 0 #define IMAGE PORTB, 0 #define IMAGE_REG PORTB #define POS_BUTTON PORTB, 7 #define SET_BUTTON PORTB, 6 cblock 0x0c curline ; line currently displayed curlinegroup ; curline / 8 curcharline ; counter for displaying time curdayline ; counter for displaying day vflags ; vertical refresh flags flags ; time flags BCDHigh ; high nybble of BCD conversion result BCDLow ; low nybble of BCD conversion result setbuttoncount ; # of frames SET_BUTTON is depressed posbuttoncount ; # of frames POS_BUTTON is depressed ; these are used for debouncing, ; setting repeat rate cursorpos ; time field selected for editing temp ; scratch variable stringlength ; length of string to display timestring: 6 ; the time in string form (hhmmss) daystring: 2 ; the day in string form (dd) frames ; frame counter seconds ; second counter minutes ; minute counter hours ; hour counter days ; day counter us_low ; microseconds, low byte us_mid ; microseconds, middle byte us_high ; microseconds, high byte eohstring1:4 ; 'TILL' eohstring2:3 ; 'EOH' eohstring3:4 ; 'DAYS' stringline ; counter for string display endc ; convenience macros for accessing bits #define VSYNC vflags, 0 #define VEQ vflags, 1 #define countdowndone flags, 0 org 0 goto Initialize ; delay routines to delay a specified number of cycles delay10:NOP delay9: NOP delay8: NOP delay7: NOP delay6: NOP delay5: NOP delay4: RETURN ; call appropriate handler for the line currently being displayed GetLineHandler: ; cycle # | comment ADDWF PCL, F ; 27 GOTO VBlank1 ; 29 lines 000-007 vertical blanking GOTO VBlank2 ; 29 lines 008-015 vertical blanking GOTO Black ; 29 lines 016-023 black lines GOTO Black ; 29 lines 024-031 black lines GOTO Black ; 29 lines 032-039 black lines GOTO Black ; 29 lines 040-047 black lines GOTO Black ; 29 lines 048-055 black lines GOTO Black ; 29 lines 056-063 black lines GOTO DrawDayString ; 29 lines 064-071 large day display GOTO DrawDayString ; 29 lines 072-079 large day display GOTO DrawDayString ; 29 lines 080-087 large day display GOTO DrawDayString ; 29 lines 088-095 large day display GOTO DrawDayString ; 29 lines 096-103 large day display GOTO DrawDayString ; 29 lines 104-111 large day display GOTO DrawDayString ; 29 lines 112-119 large day display GOTO Black ; 29 lines 120-127 black lines GOTO Black ; 29 lines 128-135 black lines GOTO DrawEOHString3 ; 29 lines 136-143 'DAYS' GOTO DrawEOHString3 ; 29 lines 144-151 'DAYS' GOTO Black ; 29 lines 152-159 black lines GOTO DrawTimeString ; 29 lines 160-167 time display GOTO DrawTimeString ; 29 lines 168-175 time display GOTO Black ; 29 lines 176-183 black lines GOTO DrawEOHString1 ; 29 lines 184-191 'TILL' GOTO DrawEOHString1 ; 29 lines 192-199 'TILL' GOTO DrawEOHString2 ; 29 lines 200-207 'EOH' GOTO DrawEOHString2 ; 29 lines 208-215 'EOH' GOTO Black ; 29 lines 216-223 black lines GOTO Black ; 29 lines 224-231 black lines GOTO Black ; 29 lines 232-239 black lines GOTO Black ; 29 lines 240-247 black lines GOTO Black ; 32 lines 248-255 black lines ; Vertical equalization/synchronization, defer to other handlers VBlank1: MOVLW d'7' ; 31 find current line # mod 8 ANDWF curline, W ; 32 and run appropriate handler ADDWF PCL, F ; 33 GOTO VertEqualize ; 35 line 0 equalizing pulses GOTO VertEqualize ; 35 line 1 equalizing pulses GOTO VertEqualize ; 35 line 2 equalizing pulses GOTO VertSynchronize ; 35 line 3 synchronizing pulses GOTO VertSynchronize ; 35 line 4 synchronizing pulses GOTO VertSynchronize ; 35 line 5 synchronizing pulses GOTO VertEqualize ; 35 line 6 equalizing pulses GOTO VertEqualize ; 35 line 7 equalizing pulses ; Vertical equalization/synchronization and other calculations ; occur on these lines, defer to line-specific handlers VBlank2: MOVLW d'7' ; 31 find current line # mod 8 ANDWF curline, W ; 32 and run appropriate handler ADDWF PCL, F ; 33 GOTO VertEqualize ; 35 line 8 equalizing pulses GOTO CalcTime ; 35 line 9 Calculate time GOTO BuildTimeString1 ; 35 line 10 converts hours to string GOTO BuildTimeString2 ; 35 line 10 converts mins to string GOTO BuildTimeString3 ; 35 line 10 converts secs to string GOTO HandleButtons ; 35 line 13 reads the buttons GOTO BuildDayString1 ; 35 line 14 converts days to string GOTO Black ; 35 line 15 blank Initialize: ; Reset entry point. Set up PIC to run program BSF STATUS, RP0 CLRF TRISA ; set all ports as outputs CLRF TRISB BCF OPTION_REG, T0CS ; enable TMR0 BCF STATUS, RP0 CLRF PORTA ; initialize outputs to zeros CLRF PORTB CLRF days ; clear all counters CLRF hours CLRF minutes CLRF seconds CLRF frames CLRF us_high CLRF us_mid CLRF us_low CLRF curline BSF countdowndone ; initially don't count MOVLW d'3' ; set up button debounce counters MOVWF posbuttoncount MOVWF setbuttoncount BSF SYNC ; initialize to black level BCF IMAGE CLRF cursorpos MOVLW 3+4+4 ; initialize 3 strings all at once MOVWF stringlength ; i'm caching them in memory MOVLW d'3' ; arrays because it takes MOVWF PCLATH ; 6 cycles to do a table MOVLW eohstring1 ; lookup, and there isn't enough MOVWF FSR ; time to do that while CLRF temp ; drawing the string StringInitLoop: MOVF temp, W CALL GetStringChars MOVWF INDF INCF FSR, F INCF temp, F DECFSZ stringlength, F GOTO StringInitLoop CLRF PCLATH CLRF vflags ; 187 clear vertical refresh flags MOVF curline, W ; 188 start determining if SUBLW d'3' ; 189 we're in vertical refresh period GOTO DrawLine ; 190 and start drawing the screen WaitForSync: ; Poll the timer to detect when it overflows ; Timer must hit zero at cycle 185 here for the polling to work, ; so adjust the program counter to make this happen MOVF TMR0,W ; 177 (8 cycles before test) ANDLW 0x3 ; 178 align by adding TMR0 % 4 ADDWF PCL,F ; 179 to PC NOP ; 181 NOP ; 182 NOP ; 183 NOP ; 184 WaitForTimerOverflow: MOVF TMR0,W ; 185 wait for the overflow BTFSS STATUS, Z ; 186 GOTO WaitForTimerOverflow ; 187 INCF curline, F ; 188 ; this is a bit confusing because I interleaved some math ; with the synchronization pulses. The code here is checking ; to see what type of line is being drawn while it's producing ; horizontal or vertical synchronization pulses CLRF vflags ; 189 MOVF curline, W ; 190 SUBLW d'3' ; 191 DrawLine: ; Start drawing next line BCF IMAGE ; 0 start "Front Porch" 4 cycle BTFSS STATUS, C ; 1 lines 0-2 are BSF VEQ ; 2 vertical equalizing pulses SUBLW d'3' ; 3 BCF SYNC ; 4 start "Horiz Sync" 12 cycles BTFSS STATUS, C ; 5 lines 3-5 are BSF VSYNC ; 6 vertical sync pulses SUBLW d'3' ; 7 BTFSS STATUS, C ; 8 lines 6-8 are BSF VEQ ; 9 vertical equalizing pulses BTFSC VEQ ; 10 stop sync pulse BSF SYNC ; 11 if in vert equalizing region BCF STATUS,C ; 12 MOVF curline, W ; 13 divide current line number MOVWF curlinegroup ; 14 by 8 to determine line handler BTFSS VSYNC ; 15 keep at sync level if still ; in vertical sync period BSF SYNC ; 16 start "Back Porch" 24 cycles RRF curlinegroup, F ; 17 continue dividing... RRF curlinegroup, F ; 18 RRF curlinegroup, F ; 19 MOVLW h'1f' ; 20 mask away extra junk ANDWF curlinegroup, F ; 21 MOVLW d'256'-d'185'+d'24' ; 22 initialize timer to sync up MOVWF TMR0 ; 23 with end of scan line MOVF curlinegroup, W ; 24 timer doesn't start until GOTO GetLineHandler ; 25 this line ; generic blank line handlers White: BSF IMAGE Black: GOTO WaitForSync VertEqualize: ; generate a vertical equalizing pulse 7 cycles long ; starting at cycle 100 CALL delay10 ; 37 CALL delay10 ; 47 CALL delay10 ; 57 CALL delay10 ; 67 CALL delay10 ; 77 CALL delay10 ; 87 NOP ; 97 NOP ; 98 NOP ; 99 BCF SYNC ; 100 CALL delay6 ; 101 BSF SYNC ; 107 GOTO WaitForSync VertSynchronize: ; generate vertical synch serration pulse 16 cycles long ; starting at cycle 84 CALL delay10 ; 37 CALL delay10 ; 47 CALL delay10 ; 57 CALL delay10 ; 67 CALL delay7 ; 77 BSF SYNC ; 84 CALL delay6 ; 85 BCF SYNC ; 91 GOTO WaitForSync CalcTime: ; update all time counters ; first update frame counter INCF frames, F ; note that there are 61 frames MOVLW d'61' ; per second since the XORWF frames, W ; timing is not really to the BTFSC STATUS, Z ; NTSC spec CLRF frames BTFSC countdowndone ; only update other counters if GOTO WaitForSync ; if count down mode ; microsecond counter stored as 24-bit number ; each frame, subtract 16384 from this number MOVLW 0x40 ; canned 16-bit subtract routine SUBWF us_mid, F ; lowest byte ignored because BTFSC STATUS, C ; it's irrelevant to this GOTO CalcTimeDone ; part of the calculation DECF us_high, F ; DECF won't update the borrow flag MOVLW 0xFF ; so check to see if us_high XORWF us_high, W ; underflowed BTFSS STATUS, Z ; if it did, then borrow from GOTO CalcTimeDone ; seconds counter, otherwise ; we're done for this frame ; to borrow from seconds counter, add 1,000,000us to count MOVLW 0x40 ADDWF us_low, F BTFSC STATUS, C INCF us_mid, F MOVLW 0x42 ADDWF us_mid, F BTFSC STATUS, C INCF us_high, F MOVLW 0xF ADDWF us_high, F DECF seconds, F ; take away one second MOVLW 0xFF ; and keep borrowing if needed XORWF seconds, W ; check for underflow BTFSS STATUS, Z GOTO Black MOVLW d'59' ; reset seconds counter if MOVWF seconds ; underflow occurs DECF minutes, F ; take away one minute MOVLW 0xFF ; check for underflow XORWF minutes, W BTFSS STATUS, Z GOTO Black MOVLW d'59' ; reset minutes counter MOVWF minutes DECF hours, F MOVLW 0xFF ; check for underflow XORWF hours, W BTFSS STATUS, Z GOTO Black MOVLW d'23' MOVWF hours DECF days, F MOVLW 0xFF XORWF days, W BTFSS STATUS, Z GOTO Black ; when days have counted down to zero, stop the counter ; need to clear all the borrowed values to zeros CLRF days CLRF hours CLRF minutes CLRF seconds CLRF us_high CLRF us_mid CLRF us_low ; get out of count down mode BSF countdowndone CalcTimeDone: ; wait for end of scanline GOTO WaitForSync BuildTimeString1: ; convert hours value to string CLRF stringline MOVLW timestring MOVWF FSR MOVF cursorpos, W XORLW d'3' ; hours is cursor pos 3 BTFSS STATUS, Z GOTO BuildHoursString ; if this field is selected and MOVF frames, W ; if frames > 45, then SUBLW d'45' ; blink the numbers BTFSS STATUS, C GOTO BuildSpaceString BuildHoursString: MOVF hours, W GOTO BuildTimeString BuildTimeString2: ; convert minutes value to string MOVLW timestring+2 MOVWF FSR MOVF cursorpos, W XORLW d'2' ; minutes are position 2 BTFSS STATUS, Z GOTO BuildMinutesString MOVF frames, W ; as before, blink if selected SUBLW d'45' BTFSS STATUS, C GOTO BuildSpaceString BuildMinutesString: MOVF minutes, W GOTO BuildTimeString BuildTimeString3: MOVLW timestring+4 MOVWF FSR MOVF cursorpos, W XORLW d'1' ; seconds are position 1 BTFSS STATUS, Z GOTO BuildSecondsString MOVF frames, W ; blink if needed SUBLW d'45' BTFSS STATUS, C GOTO BuildSpaceString BuildSecondsString: MOVF seconds, W GOTO BuildTimeString BuildDayString1: ; convert day value to a string MOVLW daystring MOVWF FSR CLRF curdayline MOVF cursorpos, W XORLW d'4' ; days are position 4 BTFSS STATUS, Z GOTO BuildDayString MOVF frames, W ; blink if needed SUBLW d'45' BTFSS STATUS, C GOTO BuildSpaceString BuildDayString: MOVF days, W GOTO BuildTimeString BuildSpaceString: ; make a string of two spaces MOVLW CH_SPACE MOVWF INDF INCF FSR, F MOVWF INDF GOTO WaitForSync BuildTimeString: ; convert a number into a two-digit string CALL BCDify ; convert value into BCD MOVLW d'3' ; look up character offsets MOVWF PCLATH ; first for high nybble MOVF BCDHigh, W CALL GetCharOffset MOVWF INDF INCF FSR, F MOVF BCDLow, W ; then for low nybble CALL GetCharOffset MOVWF INDF INCF FSR, F CLRF PCLATH GOTO WaitForSync DrawDayString: ; Render the giant 64-line day counter MOVF curdayline, W ; find the current character MOVWF temp ; bitmap line to display RRF temp, F ; by dividing a line counter RRF temp, F ; by 8 RRF temp, W ANDLW 0x7 MOVWF curcharline ; draw that line of the bitmap MOVLW daystring ; set up the string we want MOVWF FSR MOVLW d'3' ; set up the high bits of the MOVWF PCLATH ; address we're looking up MOVF INDF, W ; get the character offset ADDWF curcharline, W ; look up the data for this line CALL GetCharLine MOVWF IMAGE_REG ; display it CALL delay4 ; make the pixels big with delays RRF IMAGE_REG, F CALL delay4 RRF IMAGE_REG, F CALL delay4 RRF IMAGE_REG, F CALL delay4 RRF IMAGE_REG, F CALL delay4 BCF IMAGE INCF FSR, F ; move on to next letter MOVF INDF, W ; and do the same thing ADDWF curcharline, W CALL GetCharLine MOVWF IMAGE_REG CALL delay4 RRF IMAGE_REG, F CALL delay4 RRF IMAGE_REG, F CALL delay4 RRF IMAGE_REG, F CALL delay4 RRF IMAGE_REG, F CALL delay4 BCF IMAGE INCF FSR, F INCF curdayline, F ; increment the line counter CLRF PCLATH ; restore the high PC bits GOTO WaitForSync DrawEOHString1: ; Write 'TILL' MOVLW eohstring1 MOVWF FSR MOVLW d'4' MOVWF stringlength GOTO DrawString DrawEOHString2: ; Write 'EOH' MOVLW eohstring2 MOVWF FSR MOVLW d'3' MOVWF stringlength GOTO DrawString DrawEOHString3: ; Write 'DAYS' MOVLW eohstring3 MOVWF FSR MOVLW d'4' MOVWF stringlength GOTO DrawString DrawString: ; Draw a text string to the screen ; maximum 7 characters per line due to timing considerations RRF stringline, W ; 40 ANDLW 0x7 ; 41 MOVWF curcharline ; 42 XORLW 0x7 ; 43 BTFSC STATUS, Z ; 44 GOTO DrawStringDone ; 45 MOVLW d'3' ; 46 MOVWF PCLATH ; 47 DrawStringLoop: MOVF INDF, W ; 0 ADDWF curcharline, W ; 1 CALL GetCharLine ; 2 MOVWF IMAGE_REG ; 8 RRF IMAGE_REG, F ; 9 RRF IMAGE_REG, F ; 10 RRF IMAGE_REG, F ; 11 RRF IMAGE_REG, F ; 12 BCF IMAGE ; 13 INCF FSR, F ; 14 DECFSZ stringlength, F ; 15 GOTO DrawStringLoop ; 16 DrawStringDone: INCF stringline,F ; increment line counter CLRF PCLATH ; restore PC high bits GOTO WaitForSync DrawTimeString: ; Same as "DrawString," only unrolled so it can ; display 8 characters on a single line. MOVLW timestring MOVWF FSR MOVF curline, W MOVWF curcharline RRF curcharline, W ANDLW 0x7 MOVWF curcharline XORLW 0x7 BTFSC STATUS, Z GOTO WaitForSync MOVLW timestring MOVWF FSR MOVLW d'3' MOVWF PCLATH MOVF INDF, W ADDWF curcharline, W CALL GetCharLine MOVWF IMAGE_REG RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F BCF IMAGE INCF FSR, F MOVF INDF, W ADDWF curcharline, W CALL GetCharLine MOVWF IMAGE_REG RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F BCF IMAGE INCF FSR, F MOVLW CH_COLON ADDWF curcharline, W CALL GetCharLine MOVWF IMAGE_REG RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F BCF IMAGE MOVF INDF, W ADDWF curcharline, W CALL GetCharLine MOVWF IMAGE_REG RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F BCF IMAGE INCF FSR, F MOVF INDF, W ADDWF curcharline, W CALL GetCharLine MOVWF IMAGE_REG RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F BCF IMAGE INCF FSR, F MOVLW CH_COLON ADDWF curcharline, W CALL GetCharLine MOVWF IMAGE_REG RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F BCF IMAGE MOVF INDF, W ADDWF curcharline, W CALL GetCharLine MOVWF IMAGE_REG RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F BCF IMAGE INCF FSR, F MOVF INDF, W ADDWF curcharline, W CALL GetCharLine MOVWF IMAGE_REG RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F RRF IMAGE_REG, F BCF IMAGE INCF FSR, F CLRF PCLATH GOTO WaitForSync BCDify: ; Turns a number less than 99 into two BCD numbers ; returned in BCDHigh and BCDLow ; Basically a divide by 10 with remainder routine CLRF BCDHigh MOVWF BCDLow BCD1: MOVLW 0x0A SUBWF BCDLow, W BTFSS STATUS, C RETURN MOVWF BCDLow INCF BCDHigh, F GOTO BCD1 RETURN HandleButtons ; when a button is pushed, increment hour/min once for every ; 15 fields the button is held down. This will also ; debounce the buttons ; set buttons as inputs ; this cannot be done outside of this function ; because other PORTB bits are used for rotating ; character bitmaps BSF STATUS, RP0 BSF SET_BUTTON BSF POS_BUTTON BCF STATUS, RP0 ; each time a button is pressed, count down from some preset ; number each frame and only perform the button action when zero ; is reached. This debounces the buttons and provides ; for repeat rate adjustment BTFSS POS_BUTTON GOTO SetPosition ; if button not pressed MOVLW d'3' ; reset debounce counter for 3 frames MOVWF posbuttoncount ; to register initial press GOTO CheckSetButton ; (~0.05 seconds) SetPosition: DECF posbuttoncount,F ; decrement debounce counter BTFSS STATUS, Z GOTO CheckSetButton ; when countdown is complete CLRF posbuttoncount ; reset position count to some big number BSF countdowndone ; so repeat rate is really slow INCF cursorpos,F ; move the cursor MOVLW d'5' ; if the cursor is at position 5 XORWF cursorpos, W ; then reset it to zero BTFSS STATUS, Z GOTO CheckSetButton CLRF cursorpos BCF countdowndone ; and start counting down CheckSetButton: MOVF cursorpos, F ; if cursor is at position 0 BTFSC STATUS, Z ; then ignore set button presses GOTO ButtonDone BTFSS SET_BUTTON GOTO SetTime ; if button not pressed MOVLW d'3' ; reset debounce counter MOVWF setbuttoncount GOTO ButtonDone SetTime: DECF setbuttoncount,F ; decrement debounce counter BTFSS STATUS, Z GOTO ButtonDone ; when it reaches zero MOVLW d'15' ; set repeat rate to ~1/4 sec MOVWF setbuttoncount MOVLW frames ; use indirect addressing to MOVWF FSR ; access current field MOVLW d'3' ; max value table stored in MOVWF PCLATH ; table, need PC high bits set MOVF cursorpos, W ADDWF FSR, F INCF INDF,F ; increment current field CALL GetMaxValue ; look up maximum value for CLRF PCLATH ; current field XORWF INDF,W BTFSS STATUS, Z ; and reset to 0 if max is reached GOTO ButtonDone CLRF INDF ButtonDone: ; set buttons as outputs BSF STATUS, RP0 BCF SET_BUTTON BCF POS_BUTTON BCF STATUS, RP0 GOTO WaitForSync org 0x300 GetMaxValue addwf PCL,F retlw d'00' retlw d'60' retlw d'60' retlw d'24' retlw d'99' GetCharOffset addwf PCL,F retlw CH_0 retlw CH_1 retlw CH_2 retlw CH_3 retlw CH_4 retlw CH_5 retlw CH_6 retlw CH_7 retlw CH_8 retlw CH_9 GetStringChars: ; Note: you can't change these strings unless you add letter ; bitmaps for them! addwf PCL,F retlw CH_T retlw CH_I retlw CH_L retlw CH_L retlw CH_E retlw CH_O retlw CH_H retlw CH_D retlw CH_A retlw CH_Y retlw CH_S ; All character bitmaps are stored backwards ; this is because of the output pin chosen ; to display images and the need to use ; right rotates to display the bitmaps. GetCharLine: addwf PCL,F GetCharLine1: CH_0 equ $-GetCharLine1 retlw b'01110' retlw b'11001' retlw b'11001' retlw b'10101' retlw b'10011' retlw b'10011' retlw b'01110' CH_1 equ $-GetCharLine1 retlw b'01100' retlw b'01010' retlw b'01000' retlw b'01000' retlw b'01000' retlw b'01000' retlw b'11111' CH_2 equ $-GetCharLine1 retlw b'01110' retlw b'10001' retlw b'10000' retlw b'01000' retlw b'00100' retlw b'00010' retlw b'11111' CH_3 equ $-GetCharLine1 retlw b'11111' retlw b'01000' retlw b'00100' retlw b'01000' retlw b'10000' retlw b'10000' retlw b'01111' CH_4 equ $-GetCharLine1 retlw b'01000' retlw b'01100' retlw b'01010' retlw b'11111' retlw b'01000' retlw b'01000' retlw b'01000' CH_5 equ $-GetCharLine1 retlw b'11111' retlw b'00001' retlw b'00001' retlw b'01110' retlw b'10000' retlw b'10000' retlw b'01111' CH_6 equ $-GetCharLine1 retlw b'01110' retlw b'10001' retlw b'00001' retlw b'01111' retlw b'10001' retlw b'10001' retlw b'01110' CH_7 equ $-GetCharLine1 retlw b'11111' retlw b'10001' retlw b'10000' retlw b'01000' retlw b'01000' retlw b'00100' retlw b'00100' CH_8 equ $-GetCharLine1 retlw b'01110' retlw b'10001' retlw b'10001' retlw b'01110' retlw b'10001' retlw b'10001' retlw b'01110' CH_9 equ $-GetCharLine1 retlw b'01110' retlw b'10001' retlw b'10001' retlw b'11111' retlw b'10000' retlw b'10000' retlw b'01110' CH_COLON equ $-GetCharLine1 retlw b'00000' retlw b'01110' retlw b'01110' retlw b'00000' retlw b'01110' retlw b'01110' retlw b'00000' CH_D equ $-GetCharLine1 retlw b'01111' retlw b'10001' retlw b'10001' retlw b'10001' retlw b'10001' retlw b'10001' retlw b'01111' CH_A equ $-GetCharLine1 retlw b'00100' retlw b'01010' retlw b'10001' retlw b'10001' retlw b'11111' retlw b'10001' retlw b'10001' CH_Y equ $-GetCharLine1 retlw b'10001' retlw b'01010' retlw b'01010' retlw b'00100' retlw b'00100' retlw b'00100' retlw b'00100' CH_S equ $-GetCharLine1 retlw b'11110' retlw b'00001' retlw b'00001' retlw b'01110' retlw b'10000' retlw b'10000' retlw b'01111' CH_T equ $-GetCharLine1 retlw b'11111' retlw b'00100' retlw b'00100' retlw b'00100' retlw b'00100' retlw b'00100' retlw b'00100' CH_I equ $-GetCharLine1 retlw b'11111' retlw b'00100' retlw b'00100' retlw b'00100' retlw b'00100' retlw b'00100' retlw b'11111' CH_L equ $-GetCharLine1 retlw b'00001' retlw b'00001' retlw b'00001' retlw b'00001' retlw b'00001' retlw b'00001' retlw b'11111' CH_E equ $-GetCharLine1 retlw b'11111' retlw b'00001' retlw b'00001' retlw b'00111' retlw b'00001' retlw b'00001' retlw b'11111' CH_O equ $-GetCharLine1 retlw b'01110' retlw b'10001' retlw b'10001' retlw b'10001' retlw b'10001' retlw b'10001' retlw b'01110' CH_H equ $-GetCharLine1 retlw b'10001' retlw b'10001' retlw b'10001' retlw b'11111' retlw b'10001' retlw b'10001' retlw b'10001' CH_SPACE equ $-GetCharLine1 retlw b'00000' retlw b'00000' retlw b'00000' retlw b'00000' retlw b'00000' retlw b'00000' retlw b'00000' END