[<<] [<] Page 1 of 1 [>] [>>] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Subject:
As promised, my ugly code
From: David Willmore ####@####.#### Date: 19 Mar 2004 05:30:16 +0000 Message-Id: <200403190530.i2J5U7sU031746@localhost.localdomain> Let's just see if this list accepts this as an attachment. If not, email me directly and I'll ship you off a copy of the code. Let's just take it as read that the code is under the GPL. Keep in mind, this is the *first* spin of the code. I've made no effort to make it compact nor clever. FYI, NJQRP is the New Jersey low power amateur radio club and the Packrats are a VHF/UHF/microwave contesting radio club in NJ/PA (around Trenton,NJ). The display is an extension of an idea from a Microchip application note for low pin count micros. They show how to drive N^2-N LEDs with N signal lines (by setting them to +/-/float in clever combinations. It's an 8x8 grid of LEDs with the diagonal missing (can't drive both the anode and cathode of a diode with the same signal and expect it to do anything). Then you take one half (trianle) and move it up and over one to make it a nice grid that's 7 wide and 8 high. For a 4x4: a b c d e f g h i j k l m n o p Remove the diagonal: b c d e g h i j l m n o And shift the parts back together: b c d e g h i j l m n o An 8x8 grid (8x7) is left as an exercise for the student-- who had better be patient and good with a soldering iron. The display looks pretty cool. :) Cheers, David processor p16f628 include p16f628.inc include test.def radix dec __CONFIG _BODEN_OFF & _CP_OFF & _DATA_CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT globals EQU 0x70 ; a 'name' to use for the global variable bank irq_vars EQU 0xA0 ; same thing for the interupt routine vars common_vars EQU 0x20 ; and for the run of the mill vars cblock 0x70 ; globals W_tmp ; temporary storage for W register in interupt endc cblock 0xA0 ; interupt temporary variables STATUS_tmp ; STATUS temp FSR_tmp ; FSR temp IRQ_timer ; timer for body to interupt connunications led_counter ; counter for value to display on LEDs tmp_offset ; temporary offset for display calculations display_buffer:8 ; storage buffer for display display_tris:8 ; storage buffer for tris data endc cblock 0x20 ; variables in bank 0 PCL_tmp ; temporary variable for table lookups msg_offset ; offset into message for display offset ; temporary value for calculations loop_tmp ; loop counter F_tmp ; '1's for the diagonal tmp ; just a normal temporary variable in_p ; input pointer out_p ; output pointer disp_in:7 ; bytes to shuffle into display disp_out:8 ; data to go to display endc ;constants num_rows EQU 0x08 ; number of rows in the display wait_count EQU -0x40 ; how many interupts to count between pixel scrolls VARIABLE message_len=(message_end - data_table) ; well, how long *is* it? org 0x0 goto startup org 0x4 interupt: movwf W_tmp ; save off W register swapf STATUS,w ; grab off status register swapping nibbles BANKSEL irq_vars ; set the bank to the interupt variables movwf STATUS_tmp ; save off nibble swapped status movf FSR,w ; load in FSR movwf FSR_tmp ; save off in temp register decf led_counter,w ; load in the counter - 1 addlw display_buffer ; offset pointer into buffer movwf FSR ; set FSR to point to buffer BANKSEL TRISB ; set bank to TRISB movlw 0xff movwf TRISB ; set to inputs movf INDF,w ; load in the buffer data BANKSEL PORTB ; point to port B register movwf PORTB ; set outputs movlw 0x08 ; offset from port buffer to tris buffer addwf FSR ; move the FSR BANKSEL TRISB ; point back to the TRISB bank movf INDF,w ; load the tris data movwf TRISB ; store tris data BANKSEL irq_vars ; back to the variables decfsz led_counter,w ; decrement and skip if zero goto interupt_bail ; get out movlw num_rows ; load in the number of rows interupt_bail: movwf led_counter ; write back the counter incfsz IRQ_timer,w ; increment counter and lock at 0xff movwf IRQ_timer ; write back incremented value BANKSEL INTCON bcf INTCON,T0IF ; clear timer0 interupt pending bit ; restore program context BANKSEL irq_vars movf FSR_tmp,w ; load in FSR save value movwf FSR ; save it back swapf STATUS_tmp,w ; swap nibbles of saved STATUS and save into w movwf STATUS ; move w into STATUS register swapf W_tmp,f ; swap nibbles in W_tmp swapf W_tmp,w ; swap nibbles in W_tmp and save into w retfie startup: BANKSEL CMCON movlw b'00000111' ; disable comparators and set inputs to digital mode movwf CMCON BANKSEL VRCON movlw b'00000000' ; clear out the voltage reference unit movwf VRCON BANKSEL OPTION_REG movlw b'11000010' ; setup TIMR0 movwf OPTION_REG BANKSEL led_counter movlw num_rows movwf led_counter BANKSEL TRISA ; clrf TRISA ; all PORTA to output BANKSEL irq_vars movlw b'10000000' movwf display_buffer movlw b'01000000' movwf display_buffer+0x01 movlw b'00100000' movwf display_buffer+0x02 movlw b'00010000' movwf display_buffer+0x03 movlw b'00001000' movwf display_buffer+0x04 movlw b'00000100' movwf display_buffer+0x05 movlw b'00000010' movwf display_buffer+0x06 movlw b'00000001' movwf display_buffer+0x07 movlw b'00110111' movwf display_tris+0x00 movlw b'10010111' movwf display_tris+0x01 movlw b'11000111' movwf display_tris+0x02 movlw b'11100111' movwf display_tris+0x03 movlw b'11100011' movwf display_tris+0x04 movlw b'11101001' movwf display_tris+0x05 movlw b'11101100' movwf display_tris+0x06 movlw b'00000000' movwf display_tris+0x07 BANKSEL INTCON movlw b'10100000' ; setup interupts for TIMR0 movwf INTCON ; goto $-1 ; loop forever main: BANKSEL msg_offset ; clrf msg_offset ; start at the beginning top: movlw wait_count ; start counter before we get to work BANKSEL irq_vars ; set to the right bank movwf IRQ_timer ; BANKSEL common_vars ; look at the normal stuff again clrf F_tmp ; get some zero bits comf F_tmp ; set'em all! movf msg_offset,w ; start at msg_offset movwf offset ; store it off movlw 0x7 ; bytes to grab from message movwf loop_tmp ; stuff them in the loop counter movlw disp_in ; point the indirect register at the disp_in buffer movwf FSR ; read_top: movf offset,w ; get offset call data_lookup ; get the data movwf INDF ; save it off in disp_in buffer incf FSR,f ; point to next byte in disp_in buffer incf offset,f ; point to next index in message table movf offset,w ; read it in sublw message_len ; are we ready to wrap? btfsc STATUS,Z ; skip if we're != clrf offset ; wrap to zero decfsz loop_tmp,f ; we done? goto read_top ; nope, go back and do it again. disp_shuffle: ; loop_tmp is already zero because of read loop (exit condition) movlw disp_out ; set output pointer to disp_out movwf out_p ; movlw 0x8 ; 8 bytes to output movwf offset ; just a comparison for the diaginal construction disp_byte: movlw disp_in ; set input pointer to disp_in movwf in_p ; movlw 0x8 ; 8 bits in a byte movwf loop_tmp ; set counter for 'bits left' disp_bit: movf offset,w ; load in the offset subwf loop_tmp,w ; subtract off the current bit counter btfss STATUS,Z ; skip if equal movf in_p,w ; point at disp_in btfsc STATUS,Z ; skip if not equal movlw F_tmp ; point at 1 bits movwf FSR ; set pointer rlf INDF,f ; get a bit movf out_p,w ; point to disp_out movwf FSR ; rlf INDF,f ; put it in the output buffer movf offset,w ; load in the offset subwf loop_tmp,w ; subtract off the current bit counter btfss STATUS,Z ; skip if equal incf in_p,f ; set pointer to next input byte decfsz loop_tmp,f ; take one down... goto disp_bit ; pass it around... incf out_p,f ; set pointer to next output byte decfsz offset,f ; for diagonal calculation goto disp_byte ; more to do movlw 0x8 ; 8 output bytes to copy/invert movwf loop_tmp ; set the loop conter movlw disp_out ; point in_p to disp_out movwf in_p ; movlw display_tris ; point out_p to display_tris movwf out_p ; copy_invert: movf in_p,w ; point INDF to input byte movwf FSR ; comf INDF,w ; invert and load movwf tmp ; save it in the temp var movf out_p,w ; point INDF to output byte movwf FSR ; movf tmp,w ; load it back movwf INDF ; store it in output incf in_p,f ; advance pointer incf out_p,f ; advance pointer decfsz loop_tmp,f ; loop test goto copy_invert ; do the next byte BANKSEL irq_vars ; look at irq variables disp_wait: incfsz IRQ_timer,w ; are we ready to do the next one? goto disp_wait ; busy wait BANKSEL common_vars ; back to reality comf PORTA ; toggle bits in port A incf msg_offset,f ; increment point to start of message movf msg_offset,w ; load it in sublw message_len ; are we ready to wrap? btfsc STATUS,Z ; skip if we're != goto main ; start all over goto top ; around and around we go data_lookup: movwf PCL_tmp movlw LOW data_table ; load in the low byte of the table data start address addwf PCL_tmp,f movlw HIGH data_table ; load in the high byte of the table data start address btfsc STATUS,C ; skip if carry clear addlw 1 ; stuff in the carry bit movwf PCLATH ; stick it in the high byte PC latch movf PCL_tmp,w ; load in the PCL value movwf PCL ; jump data_table: message_data: ; "Welcome to the Packrats!!" ; Char 1 'W' retlw b'01111110' retlw b'10000000' retlw b'01111000' retlw b'10000000' retlw b'01111110' retlw b'00000000' ; Char 1 'e' retlw b'01110000' retlw b'10101000' retlw b'10101000' retlw b'10101000' retlw b'00010000' retlw b'00000000' ; Char 1 'l' retlw b'10000010' retlw b'11111110' retlw b'10000000' retlw b'00000000' ; Char 27 'c' retlw b'01110000' retlw b'10001000' retlw b'10001000' retlw b'10011000' retlw b'00000000' ; Char 28 'o' retlw b'01110000' retlw b'10001000' retlw b'10001000' retlw b'10001000' retlw b'01110000' retlw b'00000000' ; Char 1 'm' retlw b'11111000' retlw b'00001000' retlw b'11110000' retlw b'00001000' retlw b'11110000' retlw b'00000000' ; Char 1 'e' retlw b'01110000' retlw b'10101000' retlw b'10101000' retlw b'10101000' retlw b'00010000' retlw b'00000000' ; Char 1 ' ' retlw b'00000000' retlw b'00000000' retlw b'00000000' ; Char 1 't' retlw b'00001000' retlw b'01111100' retlw b'10001000' retlw b'00000000' retlw b'00000000' ; Char 1 'o' retlw b'01110000' retlw b'10001000' retlw b'10001000' retlw b'10001000' retlw b'01110000' retlw b'00000000' ; Char 1 ' ' retlw b'00000000' retlw b'00000000' retlw b'00000000' ; Char 1 't' retlw b'00001000' retlw b'01111100' retlw b'10001000' retlw b'00000000' retlw b'00000000' ; Char 1 'h' retlw b'11111100' retlw b'00010000' retlw b'00010000' retlw b'11100000' retlw b'00000000' ; Char 1 'e' retlw b'01110000' retlw b'10101000' retlw b'10101000' retlw b'10101000' retlw b'00010000' retlw b'00000000' ; Char 1 ' ' retlw b'00000000' retlw b'00000000' retlw b'00000000' ; Char 1 'P' retlw b'10000010' retlw b'11111110' retlw b'10010010' retlw b'00010010' retlw b'00001100' retlw b'00000000' retlw b'00000000' ; Char 1 'a' retlw b'01000000' retlw b'10101000' retlw b'10101000' retlw b'10101000' retlw b'11110000' retlw b'00000000' ; Char 1 'c' retlw b'01110000' retlw b'10001000' retlw b'10001000' retlw b'10011000' retlw b'00000000' ; Char 1 'k' retlw b'11111110' retlw b'00100000' retlw b'01010000' retlw b'10001000' retlw b'00000000' retlw b'00000000' ; Char 1 'r' retlw b'10001000' retlw b'11110000' retlw b'10001000' retlw b'00001000' retlw b'00000000' ; Char 1 'a' retlw b'01000000' retlw b'10101000' retlw b'10101000' retlw b'10101000' retlw b'11110000' retlw b'00000000' ; Char 1 't' retlw b'00001000' retlw b'01111100' retlw b'10001000' retlw b'00000000' ; Char 1 's' retlw b'10010000' retlw b'10101000' retlw b'10101000' retlw b'01001000' retlw b'00000000' ; Char 1 '!' retlw b'00000000' retlw b'10111110' retlw b'00000000' retlw b'00000000' retlw b'10111110' retlw b'00000000' ; Char 1 ' ' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' message_end: ; Char 1 'W' retlw b'01111110' retlw b'10000000' retlw b'01111000' retlw b'10000000' retlw b'01111110' retlw b'00000000' ; Char 1 'e' retlw b'01110000' retlw b'10101000' retlw b'10101000' retlw b'10101000' retlw b'00010000' retlw b'00000000' ; Char 1 'l' retlw b'10000010' retlw b'11111110' retlw b'10000000' retlw b'00000000' ; Char 27 'c' retlw b'01110000' retlw b'10001000' retlw b'10001000' retlw b'10011000' retlw b'00000000' ; Char 28 'o' retlw b'01110000' retlw b'10001000' retlw b'10001000' retlw b'10001000' retlw b'01110000' retlw b'00000000' ; Char 1 'm' retlw b'11111000' retlw b'00001000' retlw b'11110000' retlw b'00001000' retlw b'11110000' retlw b'00000000' ; Char 1 'e' retlw b'01110000' retlw b'10101000' retlw b'10101000' retlw b'10101000' retlw b'00010000' retlw b'00000000' ; Char 1 ' ' retlw b'00000000' retlw b'00000000' retlw b'00000000' ; Char 1 't' retlw b'00001000' retlw b'01111100' retlw b'10001000' retlw b'00000000' retlw b'00000000' ; Char 1 'o' retlw b'01110000' retlw b'10001000' retlw b'10001000' retlw b'10001000' retlw b'01110000' retlw b'00000000' ; Char 1 ' ' retlw b'00000000' retlw b'00000000' retlw b'00000000' ; Char 1 't' retlw b'00001000' retlw b'01111100' retlw b'10001000' retlw b'00000000' retlw b'00000000' ; Char 1 'h' retlw b'11111100' retlw b'00010000' retlw b'00010000' retlw b'11100000' retlw b'00000000' ; Char 1 'e' retlw b'01110000' retlw b'10101000' retlw b'10101000' retlw b'10101000' retlw b'00010000' retlw b'00000000' ; Char 1 ' ' retlw b'00000000' retlw b'00000000' retlw b'00000000' ; Char 1 'N' retlw b'11111110' retlw b'00000110' retlw b'00011000' retlw b'01100000' retlw b'11111110' retlw b'00000000' retlw b'00000000' ; Char 1 'J' retlw b'01100000' retlw b'10000000' retlw b'10000000' retlw b'10000010' retlw b'01111110' retlw b'00000010' retlw b'00000000' retlw b'00000000' ; Char 1 'Q' retlw b'00111000' retlw b'01000100' retlw b'10000010' retlw b'10100010' retlw b'01000100' retlw b'10111000' retlw b'00000000' retlw b'00000000' retlw b'00000000' ; Char 1 'R' retlw b'10000010' retlw b'11111110' retlw b'00010010' retlw b'00110010' retlw b'11001100' retlw b'10000000' retlw b'00000000' retlw b'00000000' ; Char 1 'P' retlw b'10000010' retlw b'11111110' retlw b'10010010' retlw b'00010010' retlw b'00001100' retlw b'00000000' retlw b'00000000' retlw b'00000000' ; Char 1 '!' ; Char 1 '!' retlw b'00000000' retlw b'10111110' retlw b'00000000' retlw b'00000000' retlw b'10111110' retlw b'00000000' ; Char 1 ' ' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[<<] [<] Page 1 of 1 [>] [>>] |