gnupic: As promised, my ugly code


Previous by date: 19 Mar 2004 05:30:16 +0000 gplink module ordering, George M. Gallant
Next by date: 19 Mar 2004 05:30:16 +0000 Running gpsim, Milan
Previous in thread:
Next in thread:

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

Previous by date: 19 Mar 2004 05:30:16 +0000 gplink module ordering, George M. Gallant
Next by date: 19 Mar 2004 05:30:16 +0000 Running gpsim, Milan
Previous in thread:
Next in thread:


Powered by ezmlm-browse 0.20.