;***************************************************************************** ;Title : This is a program to read data from the photometer & store it in the ;EEPROM. ; ;Crystal frequency : 3.58 MHz. ;Baud rate : 9600 ; ;***************************************************************************** .include "2313def.inc" .def mncnt1 = r1 .def mncnt0 = r2 .def datmsb = r3 .def epaddr0 = r4 .def epaddr1 = r5 .def lstobs0 = r6 .def lstobs1 = r7 .def rtemp = r16 .def rtemp1 = r17 .def rtemp2 = r18 .def modeflg = r19 .def datbyt = r20 .def cnt = r21 .def cnt1 = r22 .def rtcdat = r23 .def auxcnt0 = r24 .def auxcnt1 = r25 .def rreg = r26 .def treg = r27 .def datlsb = r28 .cseg .org 0 rjmp reset rjmp acq .org 4 rjmp t1intr .org 6 rjmp tim0 reset: ldi rtemp, low(RAMEND) ; initialize stack out SPL,rtemp ldi rtemp,$17 ; setting the Baud rate out UBRR,rtemp ; Baud rate is 9600 at clock of 3.68MHz ldi rtemp,$7D ; initialize PORTB out DDRB,rtemp ldi rtemp,$BA out PORTB,rtemp ldi rtemp,$78 ; initialize PORTD out DDRD,rtemp ldi rtemp,$47 out PORTD,rtemp ldi modeflg,$00 ; initialize modeflg, lstobs0 & lstobs1 to 00 mov lstobs0,modeflg mov lstobs1,modeflg ldi rtemp,$00 ; read the timer count from EEPROM mov epaddr1,rtemp ; memory location 0000, 0001 mov epaddr0,rtemp ; timer cnt for required delay rcall epread mov mncnt1,datbyt inc epaddr0 rcall epread mov mncnt0,datbyt inc epaddr0 ; mem addr points to location 0002 ldi rtemp,$00 ; disable timer1 & timer0 out TIMSK,rtemp out TIFR,rtemp ldi rtemp,$00 ; enable ext int0 in low level mode out MCUCR,rtemp ldi rtemp,$40 ; enable external interrupt 0 out GIMSK,rtemp sei ; global interrupt enable bck: cpi modeflg,$02 breq nxt in rtemp1,PINB ; check if menu pressed andi rtemp1,$80 brne bck bck1: in rtemp1,PINB ; check if menu released andi rtemp1,$80 breq bck1 cli ; clear global intr flag ldi rtemp,$00 ; disable external interrupt 0 out GIMSK,rtemp rcall menu ; goto menu function ldi modeflg,$00 ldi rtemp,$40 ; enable external interrupt 0 out GIMSK,rtemp ldi rtemp,$00 ; clear external intr flag out GIFR,rtemp sei ; global interrupt enable rjmp bck nxt: rcall getdat ; goto getdat cpi modeflg,$07 ; if memory full then jmp to memfull breq memfull ldi rtemp,$20 ; give tag for end of observation or rtemp,lstobs1 mov datlsb,lstobs0 ; write the obs num in EEPROM mov datmsb,rtemp ; & check if memory full rcall epwrite cpi modeflg,$07 ; if modeflg = 07 breq memfull ; then jump to memfull sbi PORTD,6 ; else switch off acquire led ldi modeflg,$00 rjmp bck memfull: ldi rtemp,$00 ; disable int0 out GIMSK,rtemp ldi rtemp,$FF ; loading timer0 count out TCNT0,rtemp ldi rtemp,$00 ; timer0 stopped out TCCR0,rtemp ldi rtemp,$02 ; disable timer1 & enable timer0 out TIMSK,rtemp sei ; global interrupt enable ldi rtemp,$05 ; start timer0 out TCCR0,rtemp rjmp bck ;***************************************************************************** ;'Delay' ;******* ;Aim ; This function provides a delay ;Registers used ; rtemp : to store the count ; rtemp1 : to store the count ;Functions called ; none ;***************************************************************************** delay: push rtemp push rtemp1 ldi rtemp,$FF debck1: ldi rtemp1,$FF debck: dec rtemp1 brne debck dec rtemp brne debck1 pop rtemp1 pop rtemp ret ;***************************************************************************** ;'acq' ;***** ;Aim ; This is an interrupt service routine serviced when the acquire switch ; is pressed. It checks whether it is called from main or from acquire ; itself & accordingly sets the modeflag indicating the present status. ; If called from main it makes modeflg = 02 else if called while ; acquire is in progress it sets modeflg = 03 and returns back. ; Function disables timer1 when called. ;Registers used ; rtemp : temporary register ; modeflg : indicates the mode 00 => idle ; 01 => menu ; 02 => start of acquire ; 03 => end of acquire ; 07 => memory full ;Functions called ; Delay ;***************************************************************************** acq: push rtemp ldi rtemp,$00 ; disable timer1 out TIMSK,rtemp in rtemp,SREG push rtemp rcall delay aqbck: in rtemp,PIND ; check if acquire released andi rtemp,$04 breq aqbck rcall delay cpi modeflg,$00 ; if start of acquire brne aqnxt ; else goto aqnxt ldi modeflg,$02 ; indicate start of acquire rjmp aqnxt1 aqnxt: cpi modeflg,$02 ; if end of acquire brne aqnxt1 ; else goto aqnxt1 ldi modeflg,$03 aqnxt1: pop rtemp out SREG,rtemp ldi rtemp,$00 ; clear ext interrupt flag out GIFR,rtemp pop rtemp reti ;***************************************************************************** ;'menu' ;****** ;Aim ; This function displays the menu & takes in the choice from the user. ; It then processes the choice. It disables timers 1 & 0 on entering ; this function. It loads $01 in modeflg register, switches off the ; acquire light & then clears the screen. ;The choices are : ;1>INITIALIZE RTC ;**************** ; This gives the user the option to enter the RTC data. The format is ; specified & so are the valid values. The time starts as soon as the ; last data is entered. ;Registers used ; rtemp1 register indicating whether 2 or 4 digits should be received ; 00 => 4 digits ; 01 => 2 digits ;Functions called ; disp ; rtcwrite ;2>READ RTC ;********** ; This function reads the contents of RTC & displays it on screen. ;Registers used ; none ;Functions called ; disp ; rtcread ; rxcomp ;3>READ EEPROM ;************* ; This option allows the user to read the EEPROM. It first clears the ; screen. It prints 17 lines of data at a time each containing 26 ; bytes. It then waits for a key press & then displays the next 17 ; lines. On reaching the end of memory, it waits for a key press & ; then returns to menu. ;Registers used ; cnt1 : to scan number of bytes printed/line ; rtemp1 : to scan number of lines printed ; rtemp : temporary register ; epaddr1 : registers containing the address of the current mem location ; epaddr0 : epaddr0 - LSB , epaddr1 - MSB ; treg : contains packed hex data to be transmitted ; cnt : counter ;Functions called ; txcomp ; epread ; transmit ; disp ;4>ENTER DELAY ;************* ; This option allows the user to enter the time after which a sample ; should be taken. The number entered is in hex & it is multiplied by ; 10ms to get the time delay between 2 readings. If the delay entered ; is less than 20ms it erases it & asks for it again. It then waits for ; a key press & returns to the menu. ;Registers used ; rtemp1 : register indicating whether 2 or 4 digits should be received ; 00 => 4 digits ; 01 => 2 digits ; rtemp : temporary register ; datmsb : registers in which delay value is stored ; datlsb : (MSB & LSB) ; epaddr1 : registers containing the address of the current mem location ; epaddr0 : epaddr0 - LSB , epaddr1 - MSB ;Functions called ; epwrite ; receive ; disp ;5>READ DELAY ;************ ; This option displays the delay count entered by the user. It then ; waits for a key press & returns to the menu. ;Registers used ; rtemp : temporary register ; epaddr1 : registers containing the address of the current mem location ; epaddr0 : epaddr0 - LSB , epaddr1 - MSB ;Functions called ; rxcomp ; epread ; transmit ; disp ;6>WRITE TO FILE ;*************** ; This provides an option to write the entire data in EEPROM without any ; spaces whatsoever & waits for a key press at the end of it. ;Registers used ; rtemp : temporary register ; epaddr1 : registers containing the address of the current mem location ; epaddr0 : epaddr0 - LSB , epaddr1 - MSB ;Functions called ; rxcomp ; epread ; transmit ;7>EXIT ;****** ; This option exits the menu after clearing the screen. It initializes ; the last obs no to 00 & the memory address to 0002. ;Registers used ; cnt : counter ; treg : contains packed hex data to be transmitted ; rtemp : temporary register ; epaddr1 : registers containing the address of the current mem location ; epaddr0 : epaddr0 - LSB , epaddr1 - MSB ; lstobs1 : registers containing the value of the current obs number ; lstobs0 : lstobs0 - LSB , lstobs1 - MSB ;Functions called ; txcomp ;***************************************************************************** menu: ldi rtemp,$00 ; disable timer0 & timer1 out TIMSK,rtemp out TIFR,rtemp ; clears timer interrupt flags ldi modeflg,$01 ; indicate menu operation sbi PORTD,6 ; switch off acq LED mnbck: ldi cnt,50 ; clear the screen mnbck1: ldi treg,$0A rcall txcomp dec cnt brne mnbck1 ldi ZH,high(DSP0*2) ; display menu ldi ZL,low(DSP0*2) rcall disp mnnxt: rcall rxcomp ; get choice from user cpi rreg,$31 breq ch1 cpi rreg,$32 breq ch2 cpi rreg,$33 breq ch3tmp cpi rreg,$34 breq ch4 cpi rreg,$35 breq ch5 cpi rreg,$36 breq ch6tmp cpi rreg,$37 breq ch7tmp rjmp mnbck ch3tmp: rjmp ch3 ch6tmp: rjmp ch6 ch7tmp: rjmp exit ch5: ldi ZH,high(DSP3*2) ; display ldi ZL,low(DSP3*2) rcall disp ldi rtemp,$00 ; read the timer count from EEPROM mov epaddr1,rtemp ; memory location 0000, 0001 mov epaddr0,rtemp ; timer cnt for required delay rcall epread rcall transmit inc epaddr0 rcall epread rcall transmit ldi ZH,high(DSP4*2) ; display ldi ZL,low(DSP4*2) rcall disp rcall rxcomp ; wait for key press rjmp mnbck ch1: ldi ZH,high(DSP1*2) ; display ldi ZL,low(DSP1*2) rcall disp ldi ZH,high(DSP2*2) ; display ldi ZL,low(DSP2*2) rcall disp ldi rtemp1,$01 rcall rtcwrite rjmp mnbck ch2: ldi ZH,high(DSP1*2) ; display ldi ZL,low(DSP1*2) rcall disp ldi ZH,high(DSP3*2) ; display ldi ZL,low(DSP3*2) rcall disp rcall rtcread ldi ZH,high(DSP4*2) ; display ldi ZL,low(DSP4*2) rcall disp rcall rxcomp ; wait for key press rjmp mnbck ch4: ldi ZH,high(DSP2*2) ; display ldi ZL,low(DSP2*2) rcall disp ch4bck: ldi rtemp1,$00 ; get count rcall receive ldi rtemp,$00 ; check if count greater than 1 cp datmsb,rtemp brne ch4nxt ldi rtemp,$02 cp datlsb,rtemp brsh ch4nxt ldi ZH,high(DSP5*2) ; display ldi ZL,low(DSP5*2) rcall disp rjmp ch4bck ch4nxt: ldi rtemp,$00 ; write count to EEPROM mov epaddr1,rtemp mov epaddr0,rtemp rcall epwrite rjmp mnbck ch3: ldi cnt,50 ; clear the screen ch3bck1:ldi treg,$0A rcall txcomp dec cnt brne ch3bck1 ldi cnt1,$00 ; cnt1 : to scan number of bytes printed/line ldi rtemp1,$00 ; rtemp1 : to scan number of lines printed ldi rtemp,$00 ; memory address equated to 0000 mov epaddr1,rtemp mov epaddr0,rtemp ch3bck: rcall epread ; read & display data from rcall transmit ; current mem location inc cnt1 cpi cnt1,$1A breq ch3nxt2 ; if cnt1 not equal to 26 ldi treg,$20 ; then leave a space after the byte rcall txcomp ; & check for end of memory rjmp ch3nxt3 ch3nxt2:ldi cnt1,$00 ; if cnt1 = 26 ldi treg,$0A ; then reinitialize cnt1 to 0 rcall txcomp ; leave a line ldi treg,$0D ; come to start of line rcall txcomp inc rtemp1 ; & increment rtemp1 cpi rtemp1,$11 brne ch3nxt3 ldi rtemp1,$00 ; if rtemp1 = 17 ldi ZH,high(DSP4*2) ; then reinitialise rtemp1 to 0 ldi ZL,low(DSP4*2) ; and a new page is started after rcall disp ; user gives a key press rcall rxcomp ldi treg,$08 ; give a back space rcall txcomp ch3nxt3:ldi rtemp,$FF ; checking for end of memory cpse epaddr0,rtemp ; if lower addr = FF rjmp ch3nxt cpse epaddr1,rtemp ; then, if higher addr = FF rjmp ch3nxt1 rcall rxcomp ; then wait for key press rjmp mnbck ; and return to menu ch3nxt1:inc epaddr1 ; else inc higher & lower addr ch3nxt: inc epaddr0 ; else increment lower addr rjmp ch3bck ch6: ldi rtemp,$00 ; memory address equated to 0000 mov epaddr1,rtemp mov epaddr0,rtemp ch6bck: rcall epread ; read & transmit data from rcall transmit ; current memory location ldi rtemp,$FF ; checking for end of memory cpse epaddr0,rtemp ; if lower addr = FF rjmp ch6nxt cpse epaddr1,rtemp ; then, if higher addr = FF rjmp ch6nxt1 rcall rxcomp ; then wait for key press rjmp mnbck ; and return to menu ch6nxt1:inc epaddr1 ; else inc higher & lower addr ch6nxt: inc epaddr0 ; else increment lower addr rjmp ch6bck exit: ldi rtemp,$00 mov lstobs0,rtemp mov lstobs1,rtemp mov epaddr1,rtemp ldi rtemp,$02 mov epaddr0,rtemp ldi cnt,50 ; clear the screen mnbck2: ldi treg,$0A rcall txcomp dec cnt brne mnbck2 ret ;***************************************************************************** ;'getdat' ;******** ;Aim ; This function switches on the acquire led, writes the obs no & the ; time stamp in the EEPROM. Then it gets data from the ADC & stores it ; in the EEPROM. Subsequent samples are collected after required ; sampling period, which is generated by timer1 ISR, till aquisition ; is stopped or memory is full. ;Registers used ; rtemp : temporary register ; lstobs1 : registers containing the value of the current obs number ; lstobs0 : lstobs0 - LSB, lstobs1 - MSB ; auxcnt0 : store auxillary count value ; auxcnt1 : auxcnt0 - LSB, auxcnt1 - MSB ; datbyt : determines whether timer1 interrupt has occured ; 00 => timer1 interrupt hasn't occured ; 01 => timer1 ISR has been executed ; cnt1 : determines whether first obs of a set ; 00 => 1st obs ; 01 => any other obs ; modeflg : indicates the mode 00 => idle ; 01 => menu ; 02 => start of acquire ; 03 => end of acquire ; 07 => memory full ;Functions called ; rtcread ; adcread ;***************************************************************************** getdat: cbi PORTD,6 ; switch on acquire LED ldi r30,$60 ; initialize RAMPZ reg to $0060 ldi r31,$00 ldi cnt1,$00 ; flag indicating first obs of a set ldi rtemp,$00 ; disconnect pin OC1 from timer & PWM out TCCR1A,rtemp ; operation is disabled ldi rtemp,$11 ; load count for 10ms in compare register out OCR1AH,rtemp ldi rtemp,$7b out OCR1AL,rtemp rcall rtcread ; read RTC data & store it in SRAM ldi rtemp,$40 ; store time stamp in SRAM st Z+,rtemp ldi rtemp,$01 ; increment last obs num add lstobs0,rtemp brcc gdnxt inc lstobs1 gdnxt: ldi rtemp,$0F and lstobs1,rtemp ldi rtemp,$10 or rtemp,lstobs1 st Z+,lstobs0 ; write the obs num in SRAM st Z+,rtemp gdbck1: rcall adcread ; read data from ADC & store it cpi modeflg,$07 ; if modeflg = 07 breq gdnxt3 ; then jump to gdnxt3 ldi auxcnt0,$01 ; initialisation of auxiliary count ldi auxcnt1,$00 ldi datbyt,$00 ldi rtemp,$08 ; timer 1 stopped out TCCR1B,rtemp ldi rtemp,$00 ; load 0000 in timer 1 register out TCNT1H,rtemp out TCNT1L,rtemp out TIFR,rtemp ; clear timer interrupt flags ldi rtemp,$40 ; enable timer1 in output compare match mode out TIMSK,rtemp ldi rtemp,$0A ; start timer 1 & prescale clk/8 out TCCR1B,rtemp gdbck: cpi modeflg,$03 ; loop here till delay over or breq gdnxt1 ; acquisition stopped cpi datbyt,$00 breq gdbck gdnxt1: ldi rtemp,$00 ; disable timer1 out TIMSK,rtemp cpi modeflg,$03 ; if end of acquisition then jump breq gdnxt3 ; to gdnxt3 rjmp gdbck1 ; else get next data from ADC gdnxt3: ret ;***************************************************************************** ;'receive' ;********* ;Aim ; Function to receive 16 bits (4 digits) from comp, using the serial ; port. ;Registers used ; cnt : number of times the loop is to be run. For one run, two digits ; are taken, converted to hex and packed. ; rtemp1 : value given to cnt (00 - 2 runs ie 4 digits ; 01 - 1 run ie 2 digits) ; rreg : register in which packed received hex data present ; datmsb : registers in which data bytes are stored and returned to ; datlsb : calling function (MSB & LSB) ;Functions called ; rxcomp ; asctohex ;***************************************************************************** receive: mov cnt,rtemp1 rebck: rcall rxcomp ; get one digit from comp rcall asctohex ; convert received data to hex swap rreg ; swap nibbles cpi cnt,0 ; check where to move data (msb(0) or lsb(1)) brne renxt mov datmsb,rreg ; copy rreg to msb rjmp renxt2 renxt: mov datlsb,rreg ; copy rreg to lsb renxt2: rcall rxcomp ; get next digit from comp rcall asctohex cpi cnt,0 ; check if part of lsb or msb brne renxt1 add datmsb,rreg rjmp renxt3 renxt1: add datlsb,rreg renxt3: inc cnt cpi cnt,$01 ; check if 4 digits got breq rebck ret ; go to main if all data received ;**************************************************************************** ;'transmit' ;********** ;Aim ; Function to transmit 8 bits (2 digits) to comp, using the serial ; port. ;Registers used ; datbyt : contains data received from calling function ; treg : contains packed hex data to be transmitted ;Functions called ; txcomp ; hextoasc ;**************************************************************************** transmit: mov treg,datbyt swap treg ; swap nibbles rcall hextoasc ; convert one digit to ASCII rcall txcomp ; and transmit mov treg,datbyt rcall hextoasc ; convert next digit to ASCII rcall txcomp ; and transmit ret ; return if complete data transmitted ;***************************************************************************** ;'hextoasc' ;********** ;Aim ; Convert hex to ASCII. Hex value is passed from & ASCII value is passed ; back to calling function in register treg. ;Registers used ; rtemp : temporary register ; treg : register containing data ;Functions called ; none ;***************************************************************************** hextoasc: andi treg,$0f cpi treg,$0a brsh henxt1 ldi rtemp,$30 rjmp henxt2 henxt1: ldi rtemp,$37 henxt2: add treg,rtemp ret ;***************************************************************************** ;'asctohex' ;********** ;Aim ; Convert ASCII to hex. ASCII value to be converted is passed from & hex ; value is passed back to calling function in register rreg. ;Registers used ; rreg : register containing data ;Functions called ; none ;***************************************************************************** asctohex: cpi rreg,$40 brsh asnxt subi rreg,$30 rjmp asnxt1 asnxt: subi rreg,$37 asnxt1: ret ;***************************************************************************** ;'rxcomp' ;******** ;Aim ; Function to receive data (1 digit) from computer. Value received is ; passed to calling function through register rreg. ;Registers used ; rtemp : temporary register ; rreg : register containing data received ;Functions called ; none ;***************************************************************************** rxcomp: ldi rtemp,$10 ; enable receiver out UCR,rtemp rxpoll: sbis USR,7 ; poll to check if char received rjmp rxpoll in rreg,UDR ; put received data in rreg ret ;***************************************************************************** ;'txcomp' ;******** ;Aim ; Function to transmit data (1 digit) to computer. The value to be ; transmitted is passed from calling function into register treg. ;Registers used ; rtemp : temporary register ; treg : register containing data to be transmitted ;Functions called ; none ;***************************************************************************** txcomp: ldi rtemp, $08 ; Enable transmitter out UCR,rtemp out UDR,treg txpoll: sbis USR,5 ; Poll to check end of transmission rjmp txpoll ret ;****************************************************************************** ;'epwrite' ;********* ;Aim ; Complete function to write a word into EEPROM. ;Registers used ; datbyt : contains data to be written to EEPROM ; rtemp : temporary register ; epaddr1,epaddr0 : address registers (msb,lsb) ; datlsb,datmsb : values passed from main (lsb,msb) ; modeflg : 01 indicates function is called from menu ; 07 indicates memory is full ;Functions called ; ack ; txep ;***************************************************************************** epwrite: cpi modeflg,$01 ; write data w/o checking for end of breq epnxt3 ; memory if func called from menu ldi rtemp,$00 ; checking for end of memory cpse epaddr1,rtemp ; if higher addr = 00 rjmp epnxt3 ldi rtemp,$00 cpse epaddr0,rtemp ; then, if lower addr = 00 rjmp epnxt3 ldi modeflg,$07 ; then modeflg = 07 & ret rjmp epnxt4 ; else write data epnxt3: sbi DDRB,DDB4 ; configure PINB4 as output sbi PORTB,PINB4 ; start bit: set SDA sbi PORTB,PINB5 ; set SCL cbi PORTB,PINB4 ; clear SDA ldi rtemp,0b10100000 ; load device address of EEPROM mov datbyt,rtemp rcall txep rcall ack mov datbyt,epaddr1 ; load memory location 1 rcall txep rcall ack mov datbyt,epaddr0 ; load memory location 2 rcall txep rcall ack mov datbyt,datmsb ; write first byte to EEPROM rcall txep rcall ack mov datbyt,datlsb ; write second byte to EEPROM rcall txep rcall ack cbi PORTB,PINB4 ; stop bit:clear SDA sbi PORTB,PINB5 ; set SCL sbi PORTB,PINB4 ; set SDA cpi modeflg,$01 ; jump to end if function called from menu breq epnxt4 ldi rtemp,$FE ; if lower addr = FE cp epaddr0,rtemp brne epnxt5 inc epaddr1 ; then inc higher & lower addr twice epnxt5: inc epaddr0 ; else only inc lower addr twice inc epaddr0 epnxt4: ret ;****************************************************************************** ;'epwrite1' ;********** ;Aim ; Complete function to write 12 bytes into EEPROM. ;Registers used ; cnt1 : counter ; datbyt : register in which data to be transmitted is stored ; rtemp : temporary register ; epaddr1,epaddr0 : address registers (msb,lsb) ; datlsb,datmsb : values to be written(lsb,msb)(contain ADC data) ; modeflg : 07 indicates memory is full ; SRAM : values to be written(obs num., RTC data) ;Functions called ; ack ; txep ;***************************************************************************** epwrite1:push cnt1 ldi rtemp,$FF ; checking for end of memory cpse epaddr1,rtemp ; if higher addr = FF rjmp epnxt1 ldi rtemp,$F5 cp epaddr0,rtemp ; then, if lower addr > F4 brlo epnxt1 ldi modeflg,$07 ; then modeflg = 07 & ret rjmp epnxt2 ; else write data epnxt1: sbi DDRB,DDB4 ; configure PINB4 as output sbi PORTB,PINB4 ; start bit: set SDA sbi PORTB,PINB5 ; set SCL cbi PORTB,PINB4 ; clear SDA ldi rtemp,0b10100000 ; load device address of EEPROM mov datbyt,rtemp rcall txep rcall ack mov datbyt,epaddr1 ; load memory location 1 rcall txep rcall ack mov datbyt,epaddr0 ; load memory location 2 rcall txep rcall ack ldi cnt1,$0A epbck: ld datbyt,-Z rcall txep rcall ack dec cnt1 brne epbck mov datbyt,datmsb ; write first ADC byte to EEPROM rcall txep rcall ack mov datbyt,datlsb ; write second ADC byte to EEPROM rcall txep rcall ack cbi PORTB,PINB4 ; stop bit:clear SDA sbi PORTB,PINB5 ; set SCL sbi PORTB,PINB4 ; set SDA ldi cnt1,$0C ; increment memory addr by twelve ldi rtemp,$01 epbck1: add epaddr0,rtemp brcc epnxt inc epaddr1 epnxt: dec cnt1 brne epbck1 epnxt2: pop cnt1 ret ;**************************************************************************** ;'txep' ;****** ;Aim ; Function to write a byte to EEPROM. Value to be written is passed from ; calling function in register datbyt. ;Registers used ; cnt : to store no of bits ; datbyt : to store the data ;Functions called ; none ;***************************************************************************** txep: ldi cnt, $08 ; load counter tebck: rol datbyt ; rotate data left through carry cbi PORTB,PINB5 ; clear SCL brcc tenxt ; if carry set sbi PORTB,PINB4 ; set SDA rjmp tenxt1 ; else tenxt: cbi PORTB,PINB4 ; clear SDA tenxt1: sbi PORTB,PINB5 ; set SCL dec cnt ; decrement counter brne tebck ; if counter not zero, go back nop cbi PORTB,PINB5 ; clear SCL ret ;**************************************************************************** ;'ack' ;***** ;Aim ; To get the acknowledge signal from the EEPROM. ;Registers used ; none ;Functions used ; none ;**************************************************************************** ack: sbi PORTB,PINB5 ; set SCL cbi DDRB,DDB4 ; configure PINB4 as input acbck: sbic PINB,PINB4 ; goto calling function if SDA clear rjmp acbck ; else go back to ack nop cbi PORTB,PINB5 ; clear SCL sbi DDRB,DDB4 ; configure PINB4 as output nop ret ;****************************************************************************** ;'rxep' ;****** ;Aim ; Function to read a byte from EEPROM. Value read is returned in ; register datbyt. ;Registers used ; cnt : to store no of bits ; datbyt : to store the data read ;Functions called ; none ;***************************************************************************** rxep: cbi DDRB,DDB4 ; configure PINB4 as input sbi PORTB,PINB4 ldi cnt,$08 ; load counter ldi datbyt,0 rxbck: sbi PORTB,PINB5 ; set SCL sbic PINB,PINB4 ; if SDA set then sec ; set carry sbis PINB,PINB4 ; else clc ; clear carry rol datbyt ; rotate data received from EEPROM left cbi PORTB,PINB5 ; clear SCL dec cnt ; decrement counter brne rxbck ; if counter equals zero, goto main ret ; else jump back ;****************************************************************************** ;'epread' ;******** ;Aim ; Complete function to read a byte from EEPROM. ;Registers used ; datbyt : register in which data read is stored ; rtemp : temporary register ; epaddr1,epaddr0: address registers (msb,lsb) ;Functions called ; ack ; txep ; rxep ;***************************************************************************** epread: sbi DDRB,DDB4 ; configure PINB4 as output sbi PORTB,PINB4 ; start bit: set SDA sbi PORTB,PINB5 ; set SCL cbi PORTB,PINB4 ; clear SDA ldi datbyt,0b10100000 ; load device address rcall txep rcall ack mov datbyt,epaddr1 ; load memory location 1 rcall txep rcall ack mov datbyt,epaddr0 ; load memory location 2 rcall txep rcall ack sbi PORTB,PINB4 ; start bit: set SDA sbi PORTB,PINB5 ; set SCL cbi PORTB,PINB4 ; clear SDA ldi datbyt,0b10100001 ; load device address rcall txep rcall ack rcall rxep ; read data from EEPROM sbi PORTB,PINB5 ; give clock pulse: set SCL nop cbi PORTB,PINB5 ; clear SCL cbi DDRB,DDB4 ; configure PINB4 as output cbi PORTB,PINB4 ; stop bit: clear SDA sbi PORTB,PINB5 ; set SCL sbi PORTB,PINB4 ; set SDA ret ;***************************************************************************** ;'trchrg' ;******** ;Aim ; This function charges the battery using RTC. ;Registers used ; rtcdat : register in which data to be transmitted is stored ;Functions called ; txrtc ;***************************************************************************** trchrg: sbi DDRD,DDD4 ; configure PIND4 as output cbi PORTD,PIND3 ; clear RST* cbi PORTD,PIND5 ; clear SCLK sbi PORTD,PIND3 ; set RST* ldi rtcdat,0b10001110 ; transmit address of control register rcall txrtc ldi rtcdat,0b00000000 ; transmit data to control register rcall txrtc sbi PORTD,PIND5 ; set SCLK cbi PORTD,PIND3 ; clear RST* cbi PORTD,PIND5 ; clear SCLK sbi PORTD,PIND3 ; set RST* ldi rtcdat,0b10010000 ; transmit address of trickle charger rcall txrtc ldi rtcdat,0b10101010 ; transmit data to trickle charger rcall txrtc sbi PORTD,PIND5 ; set SCLK cbi PORTD,PIND3 ; clear RST* cbi PORTD,PIND5 ; clear SCLK sbi PORTD,PIND3 ; set RST* ldi rtcdat,$8E rcall txrtc ldi rtcdat,$80 ; disable write to RTC - enable write rcall txrtc ; protect cbi PORTD,PIND3 ; clear reset to inhibit further operations ret ;****************************************************************************** ;'rtcwrite' ;********** ;Aim ; Complete function to write data into RTC. ;Registers used ; rtcdat : register containing data to be stored in RTC ; rtemp : temporary register ; rtemp2 : temporary register ; datlsb : value passed from user ;Functions called ; txrtc ; rxcomp ; receive ;***************************************************************************** rtcwrite:sbi DDRD,DDD4 ; configure PIND4 as output cbi PORTD,PIND3 ; clear RST* cbi PORTD,PIND5 ; clear SCLK sbi PORTD,PIND3 ; set RST* ldi rtcdat,0b10001110 ; transmit address of control register rcall txrtc ldi rtcdat,0b00000000 ; transmit data to control register rcall txrtc sbi PORTD,PIND5 ; set SCLK cbi PORTD,PIND3 ; clear RST* cbi PORTD,PIND5 ; clear SCLK sbi PORTD,PIND3 ; set RST* ldi rtcdat, 0b10111110 ; initialise RTC in burst mode rcall txrtc ; transmit to RTC rcall receive ; receive seconds from comp mov rtemp2,datlsb ori datlsb,$80 ; set CH bit in seconds register mov rtcdat,datlsb rcall txrtc rcall rxcomp ; wait for key press rcall receive ; receive minutes from comp andi datlsb,$7F mov rtcdat,datlsb rcall txrtc rcall rxcomp ; wait for key press rcall receive ; receive hours from comp andi datlsb,$3F mov rtcdat,datlsb rcall txrtc rcall rxcomp ; wait for key press rcall receive ; receive date from comp andi datlsb,$3F mov rtcdat,datlsb rcall txrtc rcall rxcomp ; wait for key press rcall receive ; receive month from comp andi datlsb,$1F mov rtcdat,datlsb rcall txrtc rcall rxcomp ; wait for key press rcall receive ; receive day from comp andi datlsb,$07 mov rtcdat,datlsb rcall txrtc rcall rxcomp ; wait for key press rcall receive ; receive year from comp mov rtcdat,datlsb rcall txrtc ldi rtcdat,$00 ; write to control register rcall txrtc sbi PORTD,PIND5 ; set SCLK cbi PORTD,PIND3 ; clear RST* cbi PORTD,PIND5 ; clear SCLK sbi PORTD,PIND3 ; set RST* ldi rtcdat,$80 ; transmit addr of sec reg. rcall txrtc mov rtcdat,rtemp2 ; enable CH bit of sec reg andi rtcdat,$7F rcall txrtc sbi PORTD,PIND5 ; set SCLK cbi PORTD,PIND3 ; clear RST* cbi PORTD,PIND5 ; clear SCLK sbi PORTD,PIND3 ; set RST* ldi rtcdat,$8E rcall txrtc ldi rtcdat,$80 ; disable write to RTC - enable write rcall txrtc ; protect cbi PORTD,PIND3 ; clear RST* to inhibit further operations ret ;**************************************************************************** ;'txrtc' ;******* ;Aim ; Function to write a byte to RTC. Value to be written is passed from ; calling function in register rtcdat. ;Registers used ; cnt : to store no of bits ; rtcdat : to store the data ;Functions called ; none ;***************************************************************************** txrtc: ldi cnt,$08 ; load counter trbck: ror rtcdat ; rotate data right through carry cbi PORTD,PIND5 ; clear SCLK brcc trnxt ; if carry set sbi PORTD,PIND4 ; set I/O rjmp trnxt1 ; else trnxt: cbi PORTD,PIND4 ; clear I/O trnxt1: sbi PORTD,PIND5 ; set SCLK dec cnt ; decrement counter brne trbck ; if counter not zero, go back nop cbi PORTD,PIND5 ; clear SCLK ret ;****************************************************************************** ;'rxrtc' ;******* ;Aim ; Function to read a byte from RTC. Value read is returned in register ; rtcdat. ;Registers used ; cnt : to store no of bits ; rtcdat : to store the data read ;Functions called ; none ;***************************************************************************** rxrtc: push cnt ldi cnt,$08 ; load counter ldi rtcdat,0 rrbck: sbi PORTD,PIND5 ; set SCLK sbic PIND,PIND4 ; if I/O set then sec ; set carry sbis PIND,PIND4 ; else clc ; clear carry ror rtcdat cbi PORTD,PIND5 ; clear SCLK dec cnt ; decrement counter brne rrbck ; if counter equals zero, goto calling function pop cnt ret ; else jump back ;****************************************************************************** ;'rtcread' ;********* ;Aim ; Complete function to read data from RTC. If function called from menu, ; then it displays the data otherwise if called from getdat, it stores ; the data in SRAM. ;Registers used ; rtcdat : stores data read from RTC ; cnt : counter ; datbyt : register thru which data (hex) is transmitted to comp ; treg : transmits ASCII data to comp ; modeflg : 01 indicates function called from menu ; else called from getdat ;Functions called ; txrtc ; rxrtc ; txcomp ;***************************************************************************** rtcread: sbi DDRD,DDD4 ; configure PIND4 as output cbi PORTD,PIND3 ; clear RST* cbi PORTD,PIND5 ; clear SCLK sbi PORTD,PIND3 ; set RST* ldi rtcdat,0b10111111 ; initialise RTC in burst read rcall txrtc ldi cnt,$07 cbi DDRD,DDD4 ; configure PIND4 as input rtbck: rcall rxrtc ; get data from RTC cpi modeflg,$01 ; if function called from menu brne rtnxt ; then mov datbyt,rtcdat ; transmit data in following order : rcall transmit ; sec min hour date month day year ldi treg,$20 ; leave a space after each data byte rcall txcomp ; is read rjmp rtnxt1 rtnxt: st Z+,rtcdat ; if function called from acq ; then store data in SRAM rtnxt1: dec cnt ; decrement counter brne rtbck ; jump back if all data bytes not transmitted cbi PORTD,PIND3 ; clear RST* to inhibit further operations ret ;**************************************************************************** ;'txadc' ;******* ;Aim ; Function to write a byte to ADC. Value to be written is passed from ; calling function in register datbyt ;Registers used ; cnt : to store no of bits ; datbyt : to store the data ;Functions called ; none ;***************************************************************************** txadc: ldi cnt, $08 ; load counter tabck: rol datbyt ; rotate data left through carry cbi PORTB,PINB2 ; clear SCLK brcc tanxt ; if carry set sbi PORTB,PINB0 ; set Din rjmp tanxt1 ; else tanxt: cbi PORTB,PINB0 ; clear Din tanxt1: sbi PORTB,PINB2 ; set SCLK dec cnt ; decrement counter brne tabck ; if counter not zero, go back nop cbi PORTB,PINB2 ; clear SCLK ret ;****************************************************************************** ;'rxadc' ;******* ;Aim ; Function to read a byte from ADC. Value read is returned in register ; datbyt. ;Registers used ; cnt : to store no of bits ; datbyt : to store the data read ;Functions called ; none ;***************************************************************************** rxadc: ldi cnt,$08 ; load counter ldi datbyt, 0 rabck: sbi PORTB,PINB2 ; set SCLK sbic PINB,PINB1 ; if Dout set then sec ; set carry sbis PINB,PINB1 ; else clc ; clear carry rol datbyt cbi PORTB,PINB2 ; clear SCLK dec cnt ; decrement counter brne rabck ; if counter equals zero, goto calling function ret ; else jump back ;****************************************************************************** ;'adcread' ;********* ;Aim ; Complete function to read data from ADC & write it to EEPROM. ; If cnt1 = 00, then data (time delay, obs no & RTC data) stored in ; SRAM is written to EEPROM in a burst otherwise it is stored 2 bytes at ; a time. ;Registers used ; datbyt : register in which data read is stored ; rtemp : temporary register ; cnt1 : determines whether first obs of a set ; 00 => 1st obs ; 01 => any other obs ; datmsb,datlsb : data registers (msb,lsb) ;Functions called ; rxadc ; txadc ; epwrite ; epwrite1 ;***************************************************************************** adcread: sbi PORTB,PINB3 ; set CS* cbi PORTB,PINB2 ; clear SCLK cbi PORTB,PINB0 ; clear Din cbi PORTB,PINB3 ; clear CS*. Enable ADC ldi datbyt,0b10000111 ; load control word rcall txadc rcall rxadc ; get msb from ADC mov datmsb,datbyt rcall rxadc ; get lsb from ADC mov datlsb,datbyt sbi PORTB, PINB3 ; disable CS* for the ADC lsr datmsb ; shifting the data right ror datlsb ; by 3 bits lsr datmsb ror datlsb lsr datmsb ror datlsb ldi rtemp,$80 ; give data tag or datmsb,rtemp cpi cnt1,$00 brne adnxt rcall epwrite1 ; write RTC, obs num., ADC ldi cnt1,$01 ; data to EEPROM rjmp adnxt1 adnxt: rcall epwrite adnxt1: ret ; go back to calling function ;***************************************************************************** ;'tim0' ;****** ;Aim ; This is an interrupt service routine for timer 0. It is serviced when ; the EEPROM memory becomes full. It causes the acquire led connected to ; PIND6 to blink. ;Registers used ; rtemp2 : temporary register ; rtemp : read current status of led ;Functions called ; none ;***************************************************************************** tim0: push rtemp in rtemp,SREG push rtemp in rtemp,PORTD ; read PORTD ldi rtemp2,0b01000000 eor rtemp,rtemp2 ; complement PORTD6 out PORTD,rtemp ; out PORTD pop rtemp out SREG,rtemp pop rtemp reti ;***************************************************************************** ;'t1intr' ;******** ;Aim ; Interrupt service routine for timer 1 compare match. ;Registers used ; rtemp : temporary register ; auxcnt1,auxcnt0 : store auxiliary count value msb(1), lsb(0) ; mncnt1,mncnt0 : store main count value msb(1), lsb(0) ; datbyt : 01 indicates end of delay ;Functions called ; none ;***************************************************************************** t1intr: push rtemp ldi rtemp,$08 ; stop timer1 out TCCR1B,rtemp sei ; enable global interrupt in rtemp,SREG push rtemp cpse auxcnt1,mncnt1 ; if higher bytes are not equal rjmp t1nxt ; then jmp to t1nxt cpse auxcnt0,mncnt0 ; else if lower bytes are not equal rjmp t1nxt ; then jmp to t1nxt ldi datbyt,$01 ; indicate end of delay rjmp t1nxt2 t1nxt: inc auxcnt0 ; increment lower byte of aux counter cpi auxcnt0,$00 ; if it is zero then increment higher brne t1nxt2 ; byte of aux counter inc auxcnt1 ; else continue t1nxt2: pop rtemp out SREG,rtemp ldi rtemp,$0A ; start timer 1 & prescale clk/8 out TCCR1B,rtemp pop rtemp reti ;***************************************************************************** ;'disp' ;****** ;Aim ; This function is used to display text on the screen. Register Z points ; to the data to be printed. It is automatically incremented & data is ; displayed. FF indicates end of text. ;Registers used ; rtemp : temporary register ; treg : register containing data to be transmitted ;Functions called ; txcomp ;***************************************************************************** disp: lpm ldi rtemp,$FF cp r0,rtemp breq dinxt mov treg,r0 rcall txcomp ldi rtemp,$01 add ZL,rtemp ldi rtemp,$00 adc ZH,rtemp rjmp disp dinxt: ret ;***************************************************************************** ;Display for menu ;***************************************************************************** DSP0: .db $0C,$0C ; FF,FF .db $09,$09 ; HT,HT .db $09,$09 ; HT,HT .db $4D,$45 ; M ,E .db $4E,$55 ; N ,U .db $0D,$0A ; CR,LF .db $09,$09 ; HT,HT .db $09,$09 ; HT,HT .db $08,$7E ; BS,~ .db $7E,$7E ; ~ ,~ .db $7E,$7E ; ~ ,~ .db $7E,$0D ; ~ ,CR .db $0A,$0A ; LF,LF .db $09,$09 ; HT,HT .db $09,$31 ; HT,1 .db $2E,$20 ; . ,SP .db $49,$6E ; I ,n .db $69,$74 ; i ,t .db $69,$61 ; i ,a .db $6C,$69 ; l ,i .db $7A,$65 ; z ,e .db $20,$52 ; SP,R .db $54,$43 ; T ,C .db $0D,$0A ; CR,LF .db $09,$09 ; HT,HT .db $09,$32 ; HT,2 .db $2E,$20 ; . ,SP .db $52 ; R , .db $65,$61 ; e ,a .db $64,$20 ; d ,SP .db $52,$54 ; R ,T .db $43,$0D ; C ,CR .db $0A,$09 ; LF,HT .db $09,$09 ; HT,HT .db $33,$2E ; 3 ,. .db $20,$52 ; SP,R .db $65,$61 ; e ,a .db $64,$20 ; d ,SP .db $45,$45 ; E ,E .db $50,$52 ; P ,R .db $4F,$4D ; O ,M .db $0D,$0A ; CR,LF .db $09,$09 ; HT,HT .db $09,$34 ; HT,4 .db $2E,$20 ; . ,SP .db $45,$6E ; E ,n .db $74,$65 ; t ,e .db $72,$20 ; r ,SP .db $44,$65 ; D ,e .db $6C,$61 ; l ,a .db $79,$0D ; y ,CR .db $0A,$09 ; LF,HT .db $09,$09 ; HT,HT .db $35,$2E ; 5 ,. .db $20,$52 ; SP,R .db $65,$61 ; e ,a .db $64,$20 ; d ,SP .db $44,$65 ; D ,e .db $6C,$61 ; l ,a .db $79,$0D ; y ,CR .db $0A,$09 ; LF,HT .db $09,$09 ; HT,HT .db $36,$2E ; 6 ,. .db $20,$57 ; SP,W .db $72,$69 ; r ,i .db $74,$65 ; t ,e .db $20,$74 ; SP,t .db $6F,$20 ; o ,SP .db $46,$69 ; F ,i .db $6C,$65 ; l ,e .db $0D,$0A ; CR,LF .db $09,$09 ; HT,HT .db $09 ; HT .db $37,$2E ; 7 ,. .db $20,$45 ; SP,E .db $78,$69 ; x ,i .db $74,$0D ; t ,CR .db $0A,$0A ; LF,LF .db $09,$09 ; HT,HT .db $09,$45 ; HT,E .db $6E,$74 ; n ,t .db $65,$72 ; e ,r .db $20,$43 ; SP,C .db $68,$6F ; h ,o .db $69,$63 ; i ,c .db $65,$20 ; e ,SP .db $3A,$20 ; : ,SP .db $FF ; END ;***************************************************************************** ;Display for format of RTC data ;***************************************************************************** DSP1: .db $0A,$0A ; LF,LF .db $0A,$0D ; LF,CR .db $20,$20 ; SP,SP .db $20,$20 ; SP,SP .db $56,$61 ; V ,a .db $6C,$69 ; l ,i .db $64,$20 ; d ,SP .db $56,$61 ; V ,a .db $6C,$75 ; l ,u .db $65,$73 ; e ,s .db $20,$3A ; SP,: .db $20,$73 ; SP,s .db $65,$63 ; e ,c .db $6F,$6E ; o ,n .db $64,$20 ; d ,SP .db $20,$6D ; SP,m .db $69,$6E ; i ,n .db $75,$74 ; u ,t .db $65,$20 ; e ,SP .db $20,$20 ; SP,SP .db $68,$6F ; h ,o .db $75,$72 ; u ,r .db $20,$20 ; SP,SP .db $20,$20 ; SP,SP .db $64,$61 ; d ,a .db $74,$65 ; t ,e .db $20,$20 ; SP,SP .db $20,$20 ; SP,SP .db $6D,$6F ; m ,o .db $6E,$74 ; n ,t .db $68,$20 ; h ,SP .db $20,$20 ; SP,SP .db $20,$64 ; SP,d .db $61,$79 ; a ,y .db $20,$20 ; SP,SP .db $20,$20 ; SP,SP .db $79,$65 ; y ,e .db $61,$72 ; a ,r .db $0A,$0D ; LF,CR .db $09,$09 ; HT,HT .db $20,$20 ; SP,SP .db $20 ; SP .db $28,$30 ; ( ,0 .db $30,$2D ; 0 ,- .db $35,$39 ; 5 ,9 .db $29,$20 ; ) ,SP .db $28,$30 ; ( ,0 .db $30,$2D ; 0 ,- .db $35,$39 ; 5 ,9 .db $29,$20 ; ) ,SP .db $28,$30 ; ( ,0 .db $30,$2D ; 0 ,- .db $32,$33 ; 2 ,3 .db $29,$20 ; ) ,SP .db $28,$30 ; ( ,0 .db $31,$2D ; 1 ,- .db $33,$31 ; 3 ,1 .db $29,$20 ; ) ,SP .db $28,$30 ; ( ,0 .db $31,$2D ; 1 ,- .db $31,$32 ; 1 ,2 .db $29,$20 ; ) ,SP .db $28,$30 ; ( ,0 .db $31,$2D ; 1 ,- .db $30,$37 ; 0 ,7 .db $29,$20 ; ) ,SP .db $28,$30 ; ( ,0 .db $30,$2D ; 0 ,- .db $39,$39 ; 9 ,9 .db $29,$0A ; ) ,LF .db $0D,$0A ; CR,LF .db $09,$09 ; HT,HT .db $20,$46 ; SP,F .db $6F,$72 ; o ,r .db $6D,$61 ; m ,a .db $74,$20 ; t ,SP .db $69,$73 ; i ,s .db $20,$3A ; SP,: .db $20,$73 ; SP,s .db $63,$20 ; c ,SP .db $6D,$6E ; m ,n .db $20,$68 ; SP,h .db $72,$20 ; r ,SP .db $64,$74 ; d ,t .db $20,$6D ; SP,m .db $6D,$20 ; m ,SP .db $64,$64 ; d ,d .db $20,$79 ; SP,y .db $79,$FF ; y ,END ;***************************************************************************** ;Display for 'Enter Data : ' ;***************************************************************************** DSP2: .db $0A,$0A ; LF,LF .db $0D,$09 ; CR,HT .db $09,$45 ; HT,E .db $6E,$74 ; n ,t .db $65,$72 ; e ,r .db $20,$44 ; SP,D .db $61,$74 ; a ,t .db $61,$20 ; a ,SP .db $3A,$20 ; : ,SP .db $FF ; END ;***************************************************************************** ;Display for 'Data is : ' ;***************************************************************************** DSP3: .db $0A,$0A ; LF,LF .db $0D,$09 ; CR,HT .db $09,$20 ; HT,SP .db $20,$20 ; SP,SP .db $44 ; D .db $61,$74 ; a ,t .db $61,$20 ; a ,SP .db $69,$73 ; I ,s .db $20,$3A ; SP,: .db $20,$FF ; SP,END ;***************************************************************************** ;Display for 'Press any key to continue' ;***************************************************************************** DSP4: .db $0A,$0A ; LF,LF .db $0A,$0D ; LF,CR .db $09,$09 ; HT,HT .db $20,$20 ; SP,SP .db $20,$20 ; SP,SP .db $50,$72 ; P ,r .db $65,$73 ; e ,s .db $73,$20 ; s ,SP .db $61,$6E ; a ,n .db $79,$20 ; y ,SP .db $6B,$65 ; k ,e .db $79,$20 ; y ,SP .db $74,$6F ; t ,o .db $20,$63 ; SP,c .db $6F,$6E ; o ,n .db $74,$69 ; t ,i .db $6E,$75 ; n ,u .db $65,$0A ; e ,LF .db $0A,$0D ; LF,CR .db $FF ; END ;***************************************************************************** ;Display for erasing wrong data entered & bringing the cursor to original posn ;***************************************************************************** DSP5: .db $08,$08 ; BS,BS .db $08,$08 ; BS,BS .db $20,$20 ; SP,SP .db $20,$20 ; SP,SP .db $08,$08 ; BS,BS .db $08,$08 ; BS,BS .db $FF ; END ;*****************************************************************************