; 	****    ****
; Subroutines

; talkwordx set, where x is a word or numeral

talkword0
	call	talkphonemeZZ
	call	talkphonemeEH
	call	talkphonemeRR2
	call	talkphonemeOW
	return

talkword1
	call	talkphonemeWW
	call	talkphonemeAO
	call	talkphonemeNN1
	return

talkword2
	call	talkphonemeTT2
	call	talkphonemeUW2
	return

talkword3
	call	talkphonemeTH
	call	talkphonemeRR2
	call	talkphonemeIY
	return

talkword4
	call	talkphonemeFF
	call	talkphonemeOR
	return

talkword5
	call	talkphonemeFF
	call	talkphonemeAY
	call	talkphonemeVV
	return

talkword6
	call	talkphonemeSS
	call	talkphonemeIH
	call	talkphonemeKK2
	call	talkphonemeSS
	call	talkphonemeSS
	return

talkword7
	call	talkphonemeSS
	call	talkphonemeEH
	call	talkphonemeVV
	call	talkphonemeAX
	call	talkphonemeNN1
	return

talkword8
	call	talkphonemeEY
	call	talkphonemeTT1
	return

talkword9
	call	talkphonemeNN2
	call	talkphonemeAY
	call	talkphonemeNN1
	return

talkword10
	call	talkphonemeTT2
	call	talkphonemeEH
	call	talkphonemeNN1
	return

talkword11
	call	talkphonemeIH
	call	talkphonemeLL
	call	talkphonemeEH
	call	talkphonemeVV
	call	talkphonemeEH
	call	talkphonemeNN1
	return

talkword12
	call	talkphonemeTT2
	call	talkphonemeWW
	call	talkphonemeEH
	call	talkphonemeEL
	call	talkphonemeVV
	return

talkword13
	call	talkphonemeTH
	call	talkphonemeER2

talkwordteen
	call	talkphonemeTT2
	call	talkphonemeIY
	call	talkphonemeNN1
	return

talkword14
	call	talkword4
	goto	talkwordteen

talkword15
	call	talkphonemeFF
	call	talkphonemeIH
	call	talkphonemeFF
	goto	talkwordteen

talkword16
	call	talkword6
	goto	talkwordteen

talkword17
	call	talkword7
	goto	talkwordteen

talkword18
	call	talkword8
	goto	talkwordteen

talkword19
	call	talkword9
	goto	talkwordteen

talkword20
	call	talkphonemeTT2
	call	talkphonemeWW
	call	talkphonemeEH
	call	talkphonemeNN1

talkwordty
	call	talkphonemeTT2
	call	talkphonemeIY
	return

talkword30
	call	talkphonemeTH
	call	talkphonemeER1
	goto	talkwordty

talkword40
	call	talkword4
	goto	talkwordty

talkword50
	call	talkphonemeFF
	call	talkphonemeIH
	call	talkphonemeFF
	goto	talkwordty

talkword60
	call	talkword6
	goto	talkwordty

talkword70
	call	talkword7
	goto	talkwordty

talkword80
	call	talkword8
	goto	talkwordty

talkword90
	call	talkword9
	goto	talkwordty

talkwordhundred
	call	talkphonemeHH2
	call	talkphonemeAX
	call	talkphonemeNN1
	call	talkphonemeDD2
	call	talkphonemeRR2
	call	talkphonemeDD1
	return

talkworddepth
	call	talkphonemeDD2
	call	talkphonemeEH
	call	talkphonemeEH
	call	talkphonemePP
	call	talkphonemeTH
	goto	endword

talkwordpoint
	call	talkphonemePP
	call	talkphonemeOY
	call	talkphonemeTT1
	goto	endword

talkwordanchor
	call	talkphonemeEY
	call	talkphonemeKK3
	call	talkphonemeAE
	goto	endword

talkwordalarm
	call	talkphonemeAE
	call	talkphonemeLL
	call	talkphonemeAR
	call	talkphonemeMM
	goto	endword

talkwordon
	call	talkphonemeAO
	call	talkphonemeNG
	goto	endword

talkwordoff
	call	talkphonemeAO
	call	talkphonemeFF
	call	talkphonemeFF
	goto	endword

talkwordshallow
	call	talkphonemeSH
	call	talkphonemeAE
	call	talkphonemeLL
	call	talkphonemeOW
	goto	endword

talkwordand
	call	talkphonemeIH
	call	talkphonemeIH
	call	talkphonemeNN1
	call	talkphonemeDD2
	goto	endword

talkwordwatch
	call	talkphonemeWW
	call	talkphonemeAO
	call	talkphonemeTT1
	call	talkphonemeCH
	goto	endword

talkwordlimit
	call	talkphonemeLL
	call	talkphonemeIH
	call	talkphonemeMM
	call	talkphonemeIH
	call	talkphonemeTT1
	goto	endword

talkwordset
	call	talkphonemeSS
	call	talkphonemeSS
	call	talkphonemeEH
	call	talkphonemeTT2
	goto	endword

talkwordheading
	call	talkphonemeHH1
	call	talkphonemeEH
	call	talkphonemeDD2
	call	talkphonemeIH
	call	talkphonemeNG
	goto	endword

talkwordgps
	call	talkphonemeJH
	call	talkphonemeIY
	call	talkphonemePP
	call	talkphonemeIY
	call	talkphonemeEH
	call	talkphonemeSS
	call	talkphonemeSS
	goto	endword

talkwordno
	call	talkphonemeNN2
	call	talkphonemeOW
	goto	endword

talkworddata
	call	talkphonemeDD2
	call	talkphonemeEY
	call	talkphonemeTT2
	call	talkphonemeAX
	goto	endword

talkwordnorth
	call	talkphonemeNN2
	call	talkphonemeOR
	call	talkphonemeHH1
	goto	endword

talkwordsouth
	call	talkphonemeSS
	call	talkphonemeSS
	call	talkphonemeAW
	call	talkphonemeTH
	call	talkphonemeTH
	goto	endword

talkwordeast
	call	talkphonemeIY
	call	talkphonemeSS
	call	talkphonemeSS
	call	talkphonemeTT2 
	goto	endword

talkwordwest
	call	talkphonemeWW
	call	talkphonemeEH
	call	talkphonemeSS
	call	talkphonemeSS
	call	talkphonemeTT2
	goto	endword

talkwordposition
	call	talkphonemePP
	call	talkphonemeIH
	call	talkphonemeZZ
	call	talkphonemeIH
	call	talkphonemeSH
	call	talkphonemeNN1
	goto	endword

endword
	call	talkphonemePA5
	return
;----------------------------------------------------------------------------
; talkphonemex set, where x is the phoneme
;				Example and comments

talkphonemeAA			; hOt
	movlw	D'24'		; can be doubled
	goto	talkphoneme
talkphonemeAE			; hAt
	movlw	D'26'		; can be doubled
	goto	talkphoneme
talkphonemeAO			; AUght
	movlw	D'23'		; can be doubled
	goto	talkphoneme
talkphonemeAR			; alARm
	movlw	D'59'
	goto	talkphoneme
talkphonemeAW			; dOWn
	movlw	D'32'
	goto	talkphoneme
talkphonemeAX			; sUceed
	movlw	D'15'		; can be doubled
	goto	talkphoneme
talkphonemeAY			; kIte
	movlw	D'6'
	goto	talkphoneme
talkphonemeBB1			; riB
	movlw	D'28'		; usually preceed with 10-30 mS silence
	goto	talkphoneme
talkphonemeBB2			; Beast
	movlw	D'63'		; usually preceed with 10-30 mS silence
	goto	talkphoneme
talkphonemeCH			; CHurCH
	movlw	D'50'
	goto	talkphoneme
talkphonemeDD1			; enD
	movlw	D'21'		; usually preceed with 10-30 mS silence
	goto	talkphoneme
talkphonemeDD2			; Down
	movlw	D'33'		; usually preceed with 10-30 mS silence
	goto	talkphoneme
talkphonemeDH1			; THis
	movlw	D'18'
	goto	talkphoneme
talkphonemeDH2			; baTHe
	movlw	D'54'
	goto	talkphoneme
talkphonemeEH			; End
	movlw	D'7'		; can be doubled
	goto	talkphoneme
talkphonemeEL			; angLE
	movlw	D'62'
	goto	talkphoneme
talkphonemeER1			; lettER
	movlw	D'51'
	goto	talkphoneme
talkphonemeER2			; fERn
	movlw	D'52'
	goto	talkphoneme
talkphonemeEY			; trAY
	movlw	D'20'
	goto	talkphoneme
talkphonemeFF			; Food
	movlw	D'40'		; usually double for initial
	goto	talkphoneme
talkphonemeGG1			; Guest
	movlw	D'36'		; usually preceed with 10-30 mS silence
	goto	talkphoneme
talkphonemeGG2			; Got
	movlw	D'61'		; usually preceed with 10-30 mS silence
	goto	talkphoneme
talkphonemeGG3			; peG
	movlw	D'34'		; usually preceed with 10-30 mS silence
	goto	talkphoneme
talkphonemeHH1			; He
	movlw	D'27'		; usually double for initial
	goto	talkphoneme
talkphonemeHH2			; Hoe
	movlw	D'57'		; usually double for initial
	goto	talkphoneme
talkphonemeIH			; sIt
	movlw	D'12'		; can be doubled
	goto	talkphoneme
talkphonemeIY			; sEE
	movlw	D'19'
	goto	talkphoneme
talkphonemeJH			; JudGe
	movlw	D'10'
	goto	talkphoneme
talkphonemeKK1			; Can't
	movlw	D'42'		; usually preceed with 50-80 mS silence
	goto	talkphoneme
talkphonemeKK2			; speaK
	movlw	D'41'		; usually preceed with 50-80 mS silence
	goto	talkphoneme
talkphonemeKK3			; Crane
	movlw	D'8'		; usually preceed with 50-80 mS silence
	goto	talkphoneme
talkphonemeLL			; Like
	movlw	D'45'
	goto	talkphoneme
talkphonemeMM			; Milk
	movlw	D'16'
	goto	talkphoneme
talkphonemeNG			; aNGer
	movlw	D'44'
	goto	talkphoneme
talkphonemeNN1			; thiN
	movlw	D'11'
	goto	talkphoneme
talkphonemeNN2			; No
	movlw	D'56'
	goto	talkphoneme
talkphonemeOR			; fORtune
	movlw	D'58'
	goto	talkphoneme
talkphonemeOW			; zOne
	movlw	D'53'
	goto	talkphoneme
talkphonemeOY			; vOIce
	movlw	D'5'
	goto	talkphoneme
talkphonemePP			; Pow
	movlw	D'9'		; usually preceed with 50-80 mS silence
	goto	talkphoneme
talkphonemeRR1			; Read
	movlw	D'14'
	goto	talkphoneme
talkphonemeRR2			; cRane
	movlw	D'39'
	goto	talkphoneme
talkphonemeSH			; SHip
	movlw	D'37'		; usually double for initial
	goto	talkphoneme
talkphonemeSS			; veSt
	movlw	D'55'		; usually double for initial
	goto	talkphoneme
talkphonemeTH			; THin
	movlw	D'29'		; usually double for initial
	goto	talkphoneme
talkphonemeTT1			; parTs
	movlw	D'17'		; usually preceed with 50-80 mS silence
	goto	talkphoneme
talkphonemeTT2			; To
	movlw	D'13'		; usually preceed with 50-80 mS silence
	goto	talkphoneme
talkphonemeUH			; bOOk
	movlw	D'30'		; may be doubled
	goto	talkphoneme
talkphonemeUW1			; tO
	movlw	D'22'
	goto	talkphoneme
talkphonemeUW2			; fOOd
	movlw	D'31'
	goto	talkphoneme
talkphonemeVV			; Vest
	movlw	D'35'
	goto	talkphoneme
talkphonemeWH			; WHig
	movlw	D'48'		; usually double for initial
	goto	talkphoneme
talkphonemeWW			; We
	movlw	D'46'
	goto	talkphoneme
talkphonemeXR			; stARs
	movlw	D'47'
	goto	talkphoneme
talkphonemeYR			; hEAr
	movlw	D'60'
	goto	talkphoneme
talkphonemeYY1			; cUte
	movlw	D'49'
	goto	talkphoneme
talkphonemeYY2			; Yes
	movlw	D'25'
	goto	talkphoneme
talkphonemeZH			; pleaSure
	movlw	D'38'
	goto	talkphoneme
talkphonemeZZ			; Zoo
	movlw	D'43'
	goto	talkphoneme
talkphonemePA1			; 10 mS silence
	clrw
	goto	talkphoneme
talkphonemePA2			; 30 mS silence
	movlw	D'1'
	goto	talkphoneme
talkphonemePA3			; 50 mS silence
	movlw	D'2'
	goto	talkphoneme
talkphonemePA4			; 100 mS silence
	movlw	D'3'
	goto	talkphoneme
talkphonemePA5			; 200 mS silence
	movlw	D'4'
	goto	talkphoneme

;---------------------------------------------------------------------------
talkphoneme
; Says the phoneme whose code is in w
; Runs on into i2c_gets....
	andlw	B'00111111'	; strip top 2 bits to ensure no bad codes
	addlw	D'251'		; so a code of 5 (first non-silence code)
				; maps to 0 in the phoneme address tables
	movwf	phonemecode

; If the addition didn't overflow w then its a silence code
	btfsc	_C		; skip if its a silence code
	goto	talksoundedphon

; Its a silence code
; Timermid ticks each 69.444 usec, rolls over each 17.777 msec
; Timerhi ticks each 17.777 msec, rolls over each 4.551 seconds
; The durations of the silences are 10, 30, 50, 100 and 200 msec
; D/A sample rate is 7.2 kbytes/sec
; Adjust phonemecode so that phonemecode=1 for the shortest silence ...
; 5 for the longest silence
	movlw	D'6'
	addwf	phonemecode,f

; 10 msec is 72 D/A samples
	clrf	silencehi
	movlw	D'72'
	movwf	silencelo
	decf	phonemecode,f
	btfsc	_Z
	goto	talksilence

; 30 msec is 216 D/A samples
	movlw	D'216'
	movwf	silencelo
	decf	phonemecode,f
	btfsc	_Z
	goto	talksilence

; 50 msec is 360 D/A samples = 1 (hi), 104 (lo)
	incf	silencehi,f
	movlw	D'104'
	movwf	silencelo
	decf	phonemecode,f
	btfsc	_Z
	goto	talksilence

; 100 msec is 720 D/A samples = 2,208
	incf	silencehi,f
	movlw	D'208'
	movwf	silencelo
	decf	phonemecode,f
	btfsc	_Z
	goto	talksilence

; 200 msec is 1440 D/A samples = 5,160
	movlw	D'5'
	movwf	silencehi
	movlw	D'160'
	movwf	silencelo

; Wait til there's room in the buffer
talksilence
	decf	bufferreadoffset,w
	andlw	B'00111111'
	xorwf	bufferwriteoffset,w
	btfsc	_Z
	goto	talksilence

; Increment the buffer write offset
; The buffer is 64 bytes long
	incf	bufferwriteoffset,w
	andlw	B'00111111'
	movwf	bufferwriteoffset
; Set FSR to the write address
	addlw	pwmbuffer
	movwf	FSR
; Write D'128' (idle level) into the buffer
	movlw	D'128'
	movwf	INDF

	decf	silencelo,f
	btfss	_Z
	goto	talksilence

	movf	silencehi,f
	btfsc	_Z		; skip if more D'128's to load
	return

	decf	silencehi,f
	goto	talksilence	

talksoundedphon
	call	phonaddrhi
	movwf	addrhi
	movf	phonemecode,w
	call	phonaddrlo
	movwf	addrlo
;--

i2c_gets
; Gets bytes from the EEPROM and loads them into PWMbuffer
; Synchronises with tint by means of bufferreadoffset and bufferwriteoffset.
; bufferreadoffset is the offset of the last byte read by tint.
; bufferwriteoffset is the offset of the last byte written by i2c_gets.
; If bufferwriteoffset = bufferreadoffset-1, i2c_gets waits
;	This should only happen when writing catches up with reading
; ; If bufferwriteoffset = bufferreadoffset, tint leaves PWM unchanged
;	This should only happen when i2c_gets stops writing
; Loads bytes from EEPROM into EEbuffer
; Loads from the address in addrhi, addrlo
; Loads until a 0 byte is found, at which point it puts H80 
; into the next position in the buffer, waits until the timer isr has read
; it and exits.

; The max clock frequency for the EEproms is 400 kHz
; => 2.5 usec/cycle
; => .625 usec between transitions on SCL
; 14.7456 MHz crystal => .2713 usec instruction cycles
; so need at least 3 instructions between state changes on SCL.
; Other timing constraints are:
;	- SCL high time 600 nS min => 3 instruction cycles
;	- SCL low time 1300 nS min => 5 instruction cycles
;	- start hold time (SDA low 'til SCL low) 600 nS min => 3 cycles
;	- stop setup time (SCL hi to SDA hi) 600 nS min => 3 cycles
;	- bus free time after stop 1300 nS min => 5 instruction cycles

;----------
; Set the EEPROM address pointer to addrhi/addrlo

	call	i2c_put_start_from_both_hi

; The first four bits (b7-b4) of the control byte are the device code.
; The device code for these chips is 1010
; Bits 3-1 are the chip select bits.
; We're only using the least significant bit as we have only two EEPROM 
; devices on the bus.
; We're currently setting the EEPROM internal address pointer, so b0, the
; R/-W bit, must be clear to write 
	movlw	B'10100000'
; Bit 1 is effectively the msbit of the 16 bit address
	btfsc	addrhi,7
	addlw	B'00000010'
	movwf	i2c_byte
	call	i2c_put_byte_get_ack

; Now need to send the address to the EEPROM so it can set its address pointer
; Send the high address byte
; The first bit is "don't care"
	movf	addrhi,w
testa	movwf	i2c_byte
	call	i2c_put_byte_get_ack

; Send the low address byte
	movf	addrlo,w
	movwf	i2c_byte
	call	i2c_put_byte_get_ack

; Have now set the correct EEPROM's internal address pointer
; Need to send a start condition to read bytes
	call	i2c_put_start_from_SCL_lo

; Now need to send the control byte again, this time with the R/-W bit
; set to read from the current EEPROM address
; The first four bits (b7-b4) of the control byte are the device code.
; The device code for these chips is 1010
; Bits 3-1 are the chip select bits.
; We're only using the least significant bit as we have only two EEPROM 
; devices on the bus.
; We're about to read from the EEPROM, so b0, the
; R/-W bit, must be set to read
	movlw	B'10100001'
; Bit 1 is effectively the msbit of the 16 bit address
	btfsc	addrhi,7
	addlw	B'00000010'
	movwf	i2c_byte
	call	i2c_put_byte_get_ack

i2c_gets_anotherbyte
; Now can get a data byte from the EEPROM
	call	i2c_get_byte

;----------------------------------------------------------------------------
 #ifdef	loading
	movf	i2c_byte,w
	call	serial_send_byte
	goto	i2c_gets_inc_addr

 #endif
;----------------------------------------------------------------------------

; Now have a byte of data from EEPROM in i2c_byte

; SCL was left high by i2c_get_byte
; Need to determine whether to get another data byte from EEPROM
; (in which case should ack the last)
; or terminate data retrieval from the EEPROM
; (in which case a nack then a stop should be sent).

; If its a zero then its the end of the phoneme
	movf	i2c_byte,w
	btfsc	_Z
	goto	i2c_gets_null_found

; If there's no room in the buffer read by tint then just wait
; here until there is room
; bufferreadoffset is the offset of the last byte read by tint.
; bufferwriteoffset is the offset of the last byte written by i2c_gets.
; If bufferwriteoffset = bufferreadoffset-1, i2c_gets must wait.
i2c_gets_wait
	decf	bufferreadoffset,w
	andlw	B'00111111'
	xorwf	bufferwriteoffset,w
	btfsc	_Z
	goto	i2c_gets_wait

; Increment the buffer write offset
; The buffer is 64 bytes long
	incf	bufferwriteoffset,w
	andlw	B'00111111'
	movwf	bufferwriteoffset
; Set FSR to the write address
	addlw	pwmbuffer
	movwf	FSR
;----------

; Write the data byte from the EEPROM into the buffer
	movf	i2c_byte,w
	movwf	INDF

i2c_gets_inc_addr
; Increment the PIC's EEPROM address pointer
	incf	addrlo,f
	btfsc	_Z
	incf	addrhi,f

; If the next byte to read is at the start of a new page then need to 
; reset the EEPROM's address pointer
; The page size for these EEPROMs is 64 bytes
	movlw	B'00111111'
	andwf	addrlo,w	; set zero flag if new page
	btfsc	_Z		; skip if next read is from same page
	goto	i2c_gets_new_page_reqd

;----------
; The next byte to read from the EEPROM is on the same page as the last.
; SCL is still hi
; Send the ack
	call	i2c_put_ack
	goto	i2c_gets_anotherbyte

;----------
i2c_gets_new_page_reqd
; We need the next byte from EEPROM, but its on a new page so must
; reset the EEPROMs address pointer
; Send the nack and the stop condition
	call	i2c_put_nack
	call	i2c_put_stop

	goto	i2c_gets		; restart on the new page

;----------
i2c_gets_null_found
; The last data byte from the EEPROM was a zero
; That's it for this phoneme
	call	i2c_put_nack
	call	i2c_put_stop

	return

;----------------------------------------------------------------------------
 #ifdef loading
i2c_puts
; Loads bytes into the EEPROM, starting at 0000, ending at 65535
; Loads pages of 64 bytes.
; Synchronises with tint using pageready flag.
; bufferreadoffset is the offset of the last byte written to EEPROM.
; bufferwriteoffset is the offset of the last byte written to the buffer.
	clrf	addrhi
	clrf	addrlo

i2c_puts_newpage
i2c_puts_wait
	clrf	bufferreadoffset

; Start the write
	call	i2c_put_start_from_both_hi

i2c_puts_controlbyte
; The first four bits (b7-b4) of the control byte are the device code.
; The device code for these chips is 1010
; Bits 3-1 are the chip select bits.
; We're only using the least significant bit as we have only two EEPROM 
; devices on the bus.
; We're about to write to the EEPROM, so b0, the
; R/-W bit, must be clear to write 
	movlw	B'10100000'
; Bit 1 is effectively the msbit of the 16 bit address
	btfsc	addrhi,7
	addlw	B'00000010'
	movwf	i2c_byte
	call	i2c_put_byte_get_ack

; If the carry is set then the EEPROM sent an ack and is ready for more data
	btfsc	_C		; skip if no ack
	goto	i2c_puts_EEPROM_ready

; The EEPROM is not ready yet
	call	i2c_put_start_from_SCL_lo
	goto	i2c_puts_controlbyte

i2c_puts_EEPROM_ready
; EEPROM is ready for another page of data
; Load a byte into the serial port send register to start the PC
; sending another 64 bytes
	movf	addrhi,w
	call	serial_send_byte

; Wait until the new page has been downloaded from the PC into the buffer
i2c_puts_wait_for_page
	btfss	pageready
	goto	i2c_puts_wait_for_page

	bcf	pageready

i2c_puts_address
; Now need to send the address to the EEPROM 
; Send the high address byte
; The first bit is "don't care"
	movf	addrhi,w
	movwf	i2c_byte
	call	i2c_put_byte_get_ack

; Send the low address byte
	movf	addrlo,w
	movwf	i2c_byte
	call	i2c_put_byte_get_ack

i2c_puts_byte_loop
	movlw	pwmbuffer
	addwf	bufferreadoffset,w
	movwf	FSR
	
	movf	INDF,w
	movwf	i2c_byte
	call	i2c_put_byte_get_ack

	incf	bufferreadoffset,f
	movlw	b'00111111'
	andwf	bufferreadoffset,f
	btfss	_Z		; skip if 64 bytes done
	goto	i2c_puts_byte_loop

; 64 bytes done
	call	i2c_put_stop
	bcf	pageready
	movlw	D'64'
	addwf	addrlo,f
	btfss	_Z
	goto	i2c_puts_newpage
 
	incf	addrhi,f
	btfss	_Z		; skip if all done
	goto	i2c_puts_newpage

	return
 #endif
;----------------------------------------------------------------------------
; Low level i2c routines

; Cycle time is 271.3 nS, 2 cycles is 542 nS, near enough to 600 nS
; since we're running the EEPROMs with a 5V supply.

i2c_put_start_from_SCL_lo
; Assumes SCL lo
; Leaves SCL and SDA both low
	bsf	SDAout
	nop
	bsf	SCL
; Min start condition setup time (SCL hi 'til SDA lo) 600 nS
	nop

i2c_put_start_from_both_hi
	bcf	SDAout
; Min start hold time (SDA low 'til SCL low) 600 nS 
	nop
	bcf	SCL
	return
;-----------------------------------------

i2c_put_byte_get_ack
; Assumes SCL lo
; Sends byte in i2c_byte.
; Returns with carry set if ack, carry clear if nack received
; Leaves SCL lo
; Clock hi time 600 nS min
; Clock lo time 1300 nS min
	btfsc	i2c_byte,7
	bsf	SDAout
	btfss	i2c_byte,7
	bcf	SDAout
	bsf	SCL
	nop
	bcf	SCL

	btfsc	i2c_byte,6
	bsf	SDAout
	btfss	i2c_byte,6
	bcf	SDAout
	bsf	SCL
	nop
	bcf	SCL
	
	btfsc	i2c_byte,5
	bsf	SDAout
	btfss	i2c_byte,5
	bcf	SDAout
	bsf	SCL
	nop
	bcf	SCL
	
	btfsc	i2c_byte,4
	bsf	SDAout
	btfss	i2c_byte,4
	bcf	SDAout
	bsf	SCL
	nop
	bcf	SCL
	
	btfsc	i2c_byte,3
	bsf	SDAout
	btfss	i2c_byte,3
	bcf	SDAout
	bsf	SCL
	nop
	bcf	SCL
	
	btfsc	i2c_byte,2
	bsf	SDAout
	btfss	i2c_byte,2
	bcf	SDAout
	bsf	SCL
	nop
	bcf	SCL
	
	btfsc	i2c_byte,1
	bsf	SDAout
	btfss	i2c_byte,1
	bcf	SDAout
	bsf	SCL
	nop
	bcf	SCL
	
	btfsc	i2c_byte,0
	bsf	SDAout
	btfss	i2c_byte,0
	bcf	SDAout
	bsf	SCL
	nop
	bcf	SCL

; Get the ack
	bsf	SDAout
	nop
	nop
	bcf	_C	; assume nack initially
	bsf	SCL
	btfss	SDAin	; test if ack, skip if nack
	bsf	_C	; ack received
	bcf	SCL

	return	

;-----------------------------------------

i2c_get_byte
; Assumes SCL lo
; Gets byte from EEPROM and leaves it in i2c_byte.
; Leaves SCL and SDAout hi, ready to send either ack or nack
; Clock hi time 600 nS min
; Clock lo time 1300 nS min
	movlw	D'7'		; get seven bits in loop
	movwf	i2c_bitcount
	bsf	SDAout
	clrf	i2c_byte	; so 0 bits are rolled out
	bcf	_C		; for the first pass through the loop

i2c_get_byte_loop
	bsf	SCL	
	btfsc	SDAin
	bsf	_C
	bcf	SCL
	rlf	i2c_byte,f
	decfsz	i2c_bitcount,f
	goto	i2c_get_byte_loop
	nop

; Get the final bit
	bsf	SCL	
	btfsc	SDAin
	bsf	_C
	rlf	i2c_byte,f

; Have all the bits now in i2c_byte
; SCL is still high, SDAout is high

	return

;-----------------------------------------
i2c_put_ack
; Assumes SCL hi
; Leaves SCL low
	bcf	SCL
	bcf	SDAout
	nop
	nop
	nop
	bsf	SCL
	nop
	bcf	SCL
	return

;-----------------------------------------
i2c_put_nack
; Assumes SCL hi
; Leaves SCL low
	bcf	SCL
	bsf	SDAout
	nop
	nop
	nop
	bsf	SCL
	nop
	bcf	SCL
	return

;-----------------------------------------

i2c_put_stop
; Assumes SCL lo, doesn't care about SDAout
; Leaves SCL and SDA both high
	bcf	SDAout
	nop
	bsf	SCL
	nop
	bsf	SDAout

	return

;----------------------------------------------------------------------------
 #ifdef	serialtransmitter
serial_send_byte
; Waits for serial transmitter to be free then sends the byte in w
	movf	serialtxbitcount,f	; just set flags
	btfss	_Z
	goto	serial_send_byte

	movwf	serialtxbyte
	movlw	H'0B'
	movwf	serialtxbitcount

	return
 #endif
;----------------------------------------------------------------------------
