Firmware

The firmware for the PIC18F2455 serves as a translator between the USB and I2C protocols. There is a vendor request which essentially puts the data from the USB host into a buffer, then forwards it to the servo-controller over I2C.

At one point, another function of the firmware was to read input from a joystick for controlling the snake. Gameport joysticks use potentiometers, so the easiest way to do this was to read the voltage drop across the joystick using the ADCs in the PIC, then transferring them over USB to the USB host.

case WRITE_I2C
	banksel USB_buffer_data+wValue
	
	; I made a design decision here: we read high, low of wValue and low, 
	; high of wIndex. This is because the servo position is little endian
	; while we want to encode register number/speed
	
	movf	USB_buffer_data+wValueHigh, W, BANKED
	movwf	Transmit_buf,BANKED 
	movf	USB_buffer_data+wValue, W, BANKED
	movwf	Transmit_buf+1,BANKED
	movf	USB_buffer_data+wIndex, W, BANKED
	movwf	Transmit_buf+2,BANKED
	movf	USB_buffer_data+wIndexHigh, W, BANKED
	movwf	Transmit_buf+3,BANKED		; puts 4 bytes into transmit buffer, 
						; taken from wValue and wIndex
	movlw	low Transmit_buf
	movwf	FSR0L, ACCESS
	movlw	high Transmit_buf
	movwf	FSR0H, ACCESS			;set up the pointers to read from our array

	bsf	SSPCON2, SEN, ACCESS		; generate a start condition on the I2C bus
	repeat					; do nothing...
	untilset PIR1, SSPIF, ACCESS		; ...until I2C operation completes
	bcf	PIR1, SSPIF, ACCESS

	movlw	0xC2
	movwf	SSPBUF, ACCESS			; write the address/control byte to the I2C bus
	repeat					; do nothing...
	untilset PIR1, SSPIF, ACCESS		; ...until I2C operation completes
	bcf		PIR1, SSPIF, ACCESS
	ifset SSPCON2, ACKSTAT, ACCESS		; if the slave device did not acknowledge...
		bsf	UEP0, EPSTALL, ACCESS	; ...set EP0 protocol stall bit to 
						; signify Request Error
		break
	endi

	movlw	0x04				; put 4
	movwf	COUNTER, BANKED			; ...into COUNTER
	repeat
		movf	POSTINC0, W 		; this reads from the array and increments the 
						; pointer for us; could alternately use PLUSW 
						; to access index array; see page 74
		movwf	SSPBUF, ACCESS		; Address first byte
		repeat				; do nothing...
		untilset PIR1, SSPIF, ACCESS	; ...until I2C operation completes
		bcf	PIR1, SSPIF, ACCESS
		decf	COUNTER, F, BANKED
	until COUNTER, ==, 0

	bsf	SSPCON2, PEN, ACCESS		; generate a stop condition on the I2C bus
	repeat					; do nothing...
	untilset PIR1, SSPIF, ACCESS		; ...until I2C operation completes
	bcf	PIR1, SSPIF, ACCESS

	banksel	BD0IBC
	clrf	BD0IBC, BANKED			; set EP0 byte count to zero
	movlw	0xC8
	movwf	BD0IST, BANKED			; send packet as DATA1, set UOWN bit					
	break

Copyleft 2005: All Wrongs Reserved by Matthew Aasted (2008), Guilherme Cavalcanti (2008), Christopher Dellin (2008), Elizabeth Kneen (2008), and Jonathan Tse (2008).