where : ibrtses embedded

AVR ASM UART & Timer Interrupt

A sample application with UART and timer interrupt. Some parts of the code may have been be removed. Note that macros are published on another page.

The main unit

; running from 4MHz Quarz
; I/O
;
; DDRA:=0x00
;
; PORTA,0	: nc
; PORTA,1	: nc
; PORTA,2	: nc
; PORTA,3	: nc
; PORTA,4	: nc
; PORTA,5	: nc
; PORTA,6	: nc
; PORTA,7	: nc
;
; DDRB :=0xFF
; PORTB:=0x10 = portb_idle
;				static	action
; PORTB,0	: unnamed (23)
; PORTB,1	: unnamed (22)
; PORTB,2	: unnamed (21)
; PORTB,3	: unnamed (20)
; PORTB,4	: LED		on:=0, off:=1
; PORTB,5	: nc
; PORTB,6	: nc
; PORTB,7	: nc
; 
; DDRC:=0xFF
;
; PORTC,0	: Bus,ALTERA lsb
; PORTC,1	: Bus,ALTERA 
; PORTC,2	: Bus,ALTERA
; PORTC,3	: Bus,ALTERA
; PORTC,4	: Bus,ALTERA
; PORTC,5	: Bus,ALTERA
; PORTC,6	: Bus,ALTERA
; PORTC,7	: Bus,ALTERA msb
;
; DDRD:=0xBE	; output = 1, input = 0
;
; PORTD,0	: Rx
; PORTD,1	: Tx
; PORTD,2	: TxEnable	enable:=1, disable:=0
; PORTD,3	: interlock	conducting:=0, non conducting:=1;
; PORTD,4	: SelectEnable (38)
; PORTD,5	: WriteReg (37)
; PORTD,6	: freq_meas(36)
; PORTD,7	: nc
;
;
.nolist
.include "8535def.inc"	; includes '.device AT90S8535' directive
.list

.LISTMAC

;Assign the internal registers
; the lower half, no SBCI,SUBI,CPI,ORI,ANDI commands here
.def	timer1loop	=r1	; timer
.def 	timer1save	=r2	;
.def	timer1enable	=r3	; =1 enabled
.def	rxlen		=r4	; counting in ISR
.def	txlen		=r5	; counting in ISR
.def	timer1loop2	=r6	; timer
.def	CRCLo		=r7
.def	CRCHi		=r8
.def	CData		=r9
.def	SRC		=r10
.def	DST		=r11
.def	Cmd		=r12
.def	bshadow		=r13
.def	myflags		=r15

; the upper half, unrestricted access
.def	temp		=r16	; temporay var except IRQ
.def	U1		=r17
.def	U2		=r18
.def	U3		=r19
.def	U4		=r20
.def	U5		=r21
.def	ErrorCode	=r22
.def    rxptr		=r23	; offset from buffer
.def	txptr		=r24	; offset from buffer
.def	comstate	=r25

; r26 is the X
; r28 is the Y
; r30 is the Z

;ErrorCode : 0 = ok

;Set some constants
.equ BaudDiv		=51	; see below
.equ RxBufLen		=40	;#bytes for rx buffer
.equ TxBufLen		=250	;#bytes for tx buffer
.equ StackSize		=0x60;
.equ LastRAM		=0x25F	;fixed for this CPU
.equ Timer0Prescale	=0x04	; clk/256 =51.2us=19.53kHz
.equ Timer0Preset	=0xff	; 1 tick to overflow
.equ Timer1Prescale	=0x04	; clk/256 =51.2us=19.53kHz
.equ Timer1Preset	=0xff00	; 1 tick to overflow
.equ SWVersion		=0x01
.equ SWSubVersion	=0x00
.equ CurrentConfigSize  =16	; size of configuration
.equ defaultID		=0x04	;
.equ defaultmode	=0x10	;
.equ MaxSamples		=240	;
.equ DefaultT27		=80000	; 20ms  16777216
.equ defCaptureDiv	=0x81	; loaded into TCCR1B

.equ PortB_Idle		=0xF3;
.equ HeaderCRCSize	=8	; used for tx, incl SYN

.equ settingbytes	=21	; for communication
.equ mathbytes		=20	; for communication
.equ measbytes		=20	; for communication


.equ StackTest	=LastRAM-StackSize	; test this location
;
; baudrates @ 4MHz
; 1200 :207
; 2400 :103
; 4800 : 51
; 9600 : 25

;### Data segment ##########################

.DSEG
Dummy:		.byte 1
; measure 8 values = measbytes bytes
ADC0:		.byte 2
ADC1:		.byte 2
ADC2:		.byte 2
ADC3:		.byte 2
ADC4:		.byte 2
ADC5:		.byte 2
ADC6:		.byte 2
ADC7:		.byte 2
LastCapture:	.byte 2 ; actual capture value
CapCount:	.byte 2 ; # captures
; settings : # settingbytes
BurstADC:	.byte 1
BurstDepth:	.byte 1
DigitalIn:	.byte 1
DigitalOut:	.byte 1
DAC:		.byte 1
ServoT1:	.byte 2		; time Reg0,1
ServoT2:	.byte 2		; time Reg2,3
ServoT3:	.byte 2		; time Reg4,5
ServoT4:	.byte 2		; time Reg6,7
ServoT5:	.byte 2		; time Reg8,9
ServoT6:	.byte 2		; time Reg10,11
ServoT7:	.byte 2		; time Reg12,13
ServoT8:	.byte 2		; time Reg14,15

; math values : # mathbytes
; start EEPROM buffer
ConfigSize:	.byte 1		; size not including this
DeviceID:	.byte 1
Mode:		.byte 1
T27:		.byte 4		; loop time U11,U10,U9, blank
T15:		.byte 2
SP1:		.byte 1
SP2:		.byte 1
SP3:		.byte 1
SP4:		.byte 1
Latch1:		.byte 1
Latch2:		.byte 1

LoopTimer:	.byte 2		; timer for report

; end EEPROM buffer
; buffers
dummy2:		.byte 20
RxBuf:		.byte RxBufLen
TxBuf:		.byte TxBufLen

;Mode : behaviour of the ServoADC
;0x80 
;0x40 
;0x20 :=1 software pulse enable
;0x10 :=1 int trigger , =0 external trigger
;0x08
;0x04
;0x02
;0x01

.org	Stacktest
reservestack:	.byte StackSize ;

.ESEG		; little endian : low byte on low adress
.DB	CurrentConfigSize,defaultID,defaultmode
.DW	0,0x0010,1,0x0101,0x0101,0,0

.ORG	0x40	; device string <=31
.DB	14,'I','B','R','T',' ','X','X','X',' ','V','x','.','x','x'

.ORG	0x60	; serial <=15		= yy mm number
.DB	8,'0','1','0','2','0','0','0','1'

.ORG	0x80	; copyright msg <=31
.DB	22,'C','o','p','y','r','i','g','h','t',' ','I','B','R','T',' ','(','9','9',',','0','0',')'

.ORG	0xA0	; reference <=31
.DB	22,'h','t','t','p',':','/','/','w','w','w','.','i','b','r','t','s','e','s','.','c','o','m'

.ORG	0xC0	; userstring <=15
.DB	10,'u','s','e','r','s','t','r','i','n','g'

.ORG	0xE0

.CSEG

.org	0x00
; irq table
	rjmp	init_far	;reset
	nop			;ext irq0
	nop			;ext irq1
	nop			;timer2 compare
	nop			;timer2 overflow
	rjmp	Timer1Capture	;timer1 capture
	nop			;timer1 compareA
	nop			;timer1 compareB
	rjmp    Timer1Int	;timer1 overflow
	nop			;timer0 overflow
	nop			;SPI,STC
	rjmp	UART_RxInt	;uart rx
	rjmp	UARTTxInt	;uart tx empty
	rjmp	UARTendTx	;uart tx complete
	nop			;adc
	nop			;EEPROM
	nop			;analog comp
.org	0x11
;##############################################################
.include "POINTER.ASM"	; pointer stuff
.include "MATH.ASM"	; math stuff

; stop timer
; LastCapture:= Capturecounter
; restart timer
; myflags or $01
; inc(capcount)
;
Timer1Capture:
	push	temp
	in	temp,SREG
	push	temp
;isr
	ldi	temp,0		; stop timer1
	out	TCCR1B,temp

	clr	temp		; clear counter
	out	TCNT1H,temp
	out	TCNT1L,temp
	
	pushY
	SetYPtr	LastCapture	; get capture
	in	temp,ICR1L
	st	Y+,temp
	in	temp,ICR1H
	st	Y,temp

	ldi	temp,defCaptureDiv	; restart timer1
	out	TCCR1B,temp
	
	mov	temp,myflags	; set lsb of myflags
	ori	temp,0x01
	mov	myflags,temp

	SetYPtr	CapCount	; inc capcount
	ld	temp,Y
	inc	temp
	st	Y+,temp
	brne	t1cend
	ld	temp,Y
	inc	temp
	st	Y,temp
	
t1cend:	
;	sbi	PORTB,1
;	cbi	PORTB,1
	popY

	pop	temp
	out	SREG,temp
	pop	temp
	reti

; dec Timer1loop until zero
; then Timer1enable:=0
;
Timer1Int:
	push	temp
	in	temp,SREG
	push	temp
;isr
; reload
	ldi	temp,0xFF
	out	TCNT1H,temp
	ldi	temp,0x80	;war 0x80
	out	TCNT1L,temp
;	sbi	PORTD,4
;	cbi	PORTD,4
	
;	tst	Timer1enable
;	brne	t1iend
	mov	temp,Timer1Loop
	tst	temp
	breq	t1if
	dec	temp
	mov	Timer1loop,temp
	brne	t1iend
t1if:	
;	andi	ErrorCode,0xFB
	ldi	temp,0
	mov	Timer1Enable,temp
;	cbi	PORTD,2

;end
t1iend:
	pop	temp
	out	SREG,temp
	pop	temp
	reti
;###########################################################


.include "CONFIG.ASM"	; EEPROM stuff
.include "8535ADC.ASM"	; ADC stuff

.MACRO	SaveVar(VAR,SIZE)
	push	ZL
	push	ZH
	push	XL
	push	XH
	push	U1
	push	U2
	ldi	ZL,low(@0-ConfigSize)
	ldi	ZH,high(@0-ConfigSize)
	ldi	XL,low(@0)
	ldi	XH,high(@0)
	ldi	U1,@1
	rcall	MoveRTE
	pop	U2
	pop	U1
	pop	XH
	pop	XL
	pop	ZH
	pop	ZL
.ENDMACRO

.MACRO Ledon
	mov	temp,bshadow
	andi	temp,0xEF
	mov	bshadow,temp
	out	portb,temp
.ENDMACRO

.MACRO Ledoff
	mov	temp,bshadow
	ori	temp,0x10
	mov	bshadow,temp
	out	portb,temp
.ENDMACRO

.include "CRC.ASM"	; CRC calculation
.include "XXXX.ASM"	; Communication stuff
.include "Altera.asm"	; accessing the Altera

init_far:	rjmp	init

;.include "NSTECL.ASM"	; ControlLoop

moveETR_far:	rjmp	MoveEtr

;;wait 100us  - 118us
Wait100:
	push	u1
	push	u2
	ldi	u1,2
w1:	ldi	u2,70
w2:	dec	u2
	brne	w2
	dec	u1
	brne	w1
	pop	u2
	pop	u1
	ret
;.............................................
wait1s:	push	u1
	push	u2
	push	u3
	ldi	u3,100
wa1:	ldi	u2,200
wa2:	ldi	u1,70
wa3:	dec	u1
	brne	wa3
	dec	u2
	brne	wa2
	dec	u3
	brne	wa1
	pop	u3
	pop	u2
	pop	u1
	ret
wait500ms:		
	push	u1
	push	u2
	push	u3
	ldi	u3,50
wb1:	ldi	u2,200
wb2:	ldi	u1,70
wb3:	dec	u1
	brne	wb3
	dec	u2
	brne	wb2
	dec	u3
	brne	wb1
	pop	u3
	pop	u2
	pop	u1
	ret

wait10ms:
	push	u1
	push	u2
	push	u3
	ldi	u3,2
wc1:	ldi	u2,100
wc2:	ldi	u1,70
wc3:	dec	u1
	brne	wc3
	dec	u2
	brne	wc2
	dec	u3
	brne	wc1
	pop	u3
	pop	u2
	pop	u1
	ret

getmeasurements:
	push	U1
	push	u2
	push	u3
	push	u4
	ldi	U4,8
	ldi	u1,0
	SetYPtr	ADC0
gmloop:
	rcall	ADCChannel
	st	Y+,U3
	st	Y+,U2
	inc	u1
	dec	u4
	brne	gmloop
	pop	u4
	pop	u3
	pop	u2
	pop	u1
	ret
	
;###############################################
;  Main
;###############################################
init:
; init ports
	clr	temp
	out	porta,temp	;
	ldi	temp,PortB_Idle	; 
;	mov	bshadow,temp
	out	PORTB,temp
	clr	temp
	out	portc,temp	;
	ldi	temp,0x08	; open interlock
	out	portd,temp	;

	clr	temp
	out	DDRA,temp
	ldi	temp,0xFF
	out	DDRB,temp
	ldi	temp,0xFF
	out	DDRC,temp	; port C is output
	ldi	temp, 0xBE	; out:=1, in:=0
	out	DDRD,temp


;init stack to top of internal SRAM
	ldi	Temp,high(LastRAM)	; set SP
	out	SPH,Temp
	ldi	Temp,low(LastRAM)
	out	SPL,Temp

;init internal UART to PC
	ldi	temp,BaudDiv	; baud =???
	out	UBRR,temp
	ldi	temp,0x98	; rx&tx=0x18, rx only=0x10
	out	UCR,temp

; clear RAM		NEW !!!!
;	SetZPtr	Dummy
;	ldi	U1,0
;	ldi	U2,0xFF
;cv:	st	Z+,U1
;	dec	U2
;	brne	cv

;init vars
;  set config size
	ldi	temp,CurrentConfigSize
	setYPtr	ConfigSize
	st	Y,temp
; set ID
	ldi	temp,defaultID
	SetYPtr	DeviceID
	st	Y,temp
; set mode
	ldi	temp,defaultmode
	SetYPtr	Mode
	st	Y,temp

; set T27
	ldi	temp,0
	SetYPtr	T27
	st	Y+,temp
	ldi	temp,0
	st	Y+,temp
	ldi	temp,0x10	; =1e6
	st	Y+,temp
	ldi	temp,0
	st	Y,temp

; set T15
	ldi	temp,1
	SetYPtr	T15
	st	Y+,temp
	ldi	temp,0
	st	Y+,temp
; set sp1
	ldi	temp,2
	SetYPtr	SP1
	st	Y,temp
; set sp2
	ldi	temp,1
	SetYPtr	SP2
	st	Y,temp
; set sp3
	ldi	temp,5
	SetYPtr	SP3
	st	Y,temp
; set sp4
	ldi	temp,3
	SetYPtr	SP4
	st	Y,temp
; set latch1
	ldi	temp,0
	SetYPtr	Latch1
	st	Y,temp
; set latch2
	ldi	temp,0
	SetYPtr	Latch2
	st	Y,temp

; set math values

; set Settings values
	SetYPtr	BurstADC
	ldi	temp,0
	st	Y,temp
	SetYPtr	BurstDepth
	ldi	temp,MaxSamples
	st	Y,temp
	SetYPtr	DigitalIn
	ldi	temp,0
	st	Y,temp
	SetYPtr	DigitalOut
	ldi	temp,0
	st	Y,temp
	SetYPtr	DAC
	ldi	temp,0
	st	Y,temp

; get config
	ldi	ZL,0x0
	ldi	ZH,0x0
	SetXPtr	ConfigSize
	ld	U1,X
	inc	u1
	rcall	MoveETR_far

; disable Software_Pulse_Enable
	SetYPtr	Mode
	ld	u1,Y
	andi	u1,0xDF
	st	Y,u1

	ldi	temp,1
	mov	Timer1Loop,temp
	clr	temp
	mov	Timer1Enable,temp

; new setup
; timer1 runs on 4MHz with div1, allowing 0..16ms, or 60Hz
; timer1	; for capture
	ldi	temp,0x00
	out	TCNT1H,temp	; clear counter
	ldi	temp,0x00
	out	TCNT1L,temp
	ldi	temp,0		;no compare, no pwm
	out	TCCR1A,temp
	ldi	temp,defCaptureDiv ; 0x01
	out	TCCR1B,temp	;clk = clk
;	ldi	temp,0x24	; enable capture & overflow
;	out	TIMSK,temp
;	SEI

; timer1	; @4MHz, clk/1024 :58593.75 clocks give 15s
;	ldi	temp,0
;	out	TCCR1A,temp
;	ldi	temp,0x05
;	out	TCCR1B,temp	;clk div 1024
;	ldi	temp,0xFF
;	out	TCNT1H,temp
;	ldi	temp,0x80
;	out	TCNT1L,temp
;	ldi	temp,0x04
;	out	TIMSK,temp
;	SEI

; timer0
	ldi	temp,0		;0:=65ms
	out	TCNT0,temp
	ldi	temp,0x05
	out	TCCR0,temp

; also added
	ldi	temp,0x24      ;0x25; enable capture & overflow
	out	TIMSK,temp
;	SEI

	ldi	u1,0
	
	clr	comstate
	rcall	SetupRx
	SEI			; interrupts from here
	
tst0:
	rcall	Wait1s
	rcall	Wait1s
;	rjmp	tst0
	
	rcall	load27bit
	rcall	load15bit
	rcall	loadSP1
	rcall	loadSP2
	rcall	loadSP3
	rcall	loadSP4
	rcall	loadLatch1
	rcall	loadLatch2

main:
	Ledon
	rcall	wait10ms
	rcall	comloop
	
;       snip functionality

;	sbi	PORTD,2		;debug pulse
;	cbi	PORTD,2
		
	Ledoff

	rjmp	main

the communication

; new Vx.xx :  msg 0x23  - load FPGA from Memory
;
;
; single xxx communication unit
;  with added CRC, and SRC & DST ID
;
; protocol :
;
; index   0    1   2   3    4   5
; [SYN]  STX  LEN SRC DST  MSG [DATA] CRChi CRClo
;  0x16 0x02 ..  ..  ..        
;
; LEN = lenght including STX ... CRCHi
;
; CRC:=crc(STX..data);
; CRC poly:=
;
; rx : COMState
;  state 0 := wait for STX
;  state 1 := get len
;  state 2 := count down
;  state F := got message
;
.EQU	STX	=0x02
.EQU	SYN	=0x16

; prepares for receiving
SetupRx:
	ldi	comstate,0
	ldi	rxptr,0
	ret

; rx interrupt : one message only, up to rxbuflen bytes
;                does NOT overwrite bytes
;	         if message complete of max bytes ->comstate:=0x0F
UART_RxInt:
	push	temp
	in	temp,SREG
	push	temp
	push	U1
	pushZ
; isr
	in	U1,UDR
;	out	UDR,U1		;echo
	cpi	rxptr,RxBufLen	; test buffer full
	breq	uriterm
	mov	temp,comstate	; rxstate
	andi	temp,0x0F
	tst	temp
	brne	uri1
; state 0 - wait for STX
	cpi	u1,STX
	breq	uri0
	cpi	u1,SYN
	brne	urie
;  SYN came
	ldi	rxptr,0
	rjmp	urie
uri0:
	ldi	comstate,1
	SetZPtr	RxBuf
	st	z,u1
	inc	rxptr
	rjmp	urie
uri1:
	mov	temp,comstate
	cpi	temp,0x01
	brne	uri2
; state 1
	mov	rxlen,u1
	ldi	comstate,2
	SetZPtr	RxBuf
	add	zl,rxptr
	clr 	temp
	adc	zh,temp
	st	z,u1
	inc	rxptr
	rjmp	urie
uri2:
	mov	temp,comstate
	cpi	temp,0x02
	brne	urie	
	SetZPtr	RxBuf
	add	zl,rxptr
	clr 	temp
	adc	zh,temp
	st	z,u1
	inc	rxptr
	cp	rxptr,rxlen
	brne	urie
uriterm:
	ori	comstate,0x0F
urie:
; return
	popZ
	pop	U1
	pop	temp
	out	SREG,temp
	pop	temp
	reti


;prepare for tx
; assumes txlen is set and buffer filled
; txlen = nr of bytes
SetupTx:
	clr	txptr
	sbi	PORTD,2		; enable Tx
	sbi	UCR,UDRIE
	ret

;immediately return rxbuffer
Ping:
 	pushY
	pushZ
	push	temp
	push	u1
	SetZPtr	RxBuf
	SetYPtr	TxBuf
	mov	temp,rxptr
ping1:	ld	u1,Z+
	st	Y+,u1
	dec	temp
	brne	ping1
	
	mov	txlen,rxptr
	rcall	SetupTx
	pop	u1
	pop	temp
	popZ
	popY
	ret

;tx interrupt, requires setup of buffers
; started with SetupTx
UARTTxInt:
	push	temp
	in	temp,SREG
	push	temp
	push	U1
	pushZ
; isr
	cp	txptr,txlen ; terminate on ptr=len
	breq	utit
	SetZPtr	TxBuf
	add	zl,txptr
	clr	temp
	adc	zh,temp
	ld	u1,Z
	out	UDR,u1
	inc	txptr
	rjmp	utie
utit:	; terminate
	cbi	UCR,UDRIE	; disable TxShiftEmpty IRQ
	sbi	UCR,TXCIE	; enable TxRegEmpty IRQ
;	cbi	PORTD,2
utie:
; return
	popZ
	pop	U1
	pop	temp
	out	SREG,temp
	pop	temp
	reti

; end of Tx - clear TxEnable=PORTD,2
UARTendTx:
	push	temp
	in	temp,SREG
	push	temp
	cbi	PORTD,2
	cbi	UCR,TXCIE	; disable IRQ
	sbi	USR,TXC
	pop	temp
	out	SREG,temp
	pop	temp
	reti

; SYN STX LEN SRC DST Cmd
SetupTxFrame:	; txlen is set = #bytes to tx, incl SYN
	push	u2
	SetZPtr	TxBuf
	ldi	U2,SYN
	st	Z+,U2
	ldi	u2,STX
	st	Z+,u2
	mov	u2,txlen
	dec	u2
	st	Z+,u2
	st	Z+,DST		;reverse
	st	Z+,SRC		;reverse
	st	Z+,cmd
	pop	u2
	ret

CopyBuf:	; X^ to Z^, U2 bytes
	push	U1
cb1:	ld	U1,X+
	st	Z+,U1
	dec	u2
	tst	u2
	brne	cb1
	pop	U1
	ret

CopyRxTx:	; copies Rx to Tx
	push	U1
	push	U2
	pushY
	pushZ
	SetYPtr	RxBuf
	SetZPtr	TxBuf
	ldd	U1,Y+1
	inc	U1		; one longer for SYN
	mov	TxLen,U1
	dec	U1
	ldi	U2,SYN
	st	Z+,U2
	ldi	u2,STX
	st	Z+,U2
	st	Z+,U1		; TxLen-1 (SYN)
	st	Z+,DST		; reverse 
	st	Z+,SRC		; reverse
	st	Z+,Cmd
	subi	u1,7		; without header & crc
	SetYPtr	RxBuf
	ldi	temp,5
	add	YL,temp
	clr	temp
	adc	YH,temp
crt:
	tst	u1
	breq	crte
	ld	u2,Y+
	st	Z+,u2
	dec	u1
	rjmp	crt
crte:
	popZ
	popY
	pop	U2
	pop	U1
	ret

AddCRC:		; appends CRC,
;		  assumes msg ready, incl. TxLen
	push	u1
	SetZPtr	TxBuf
	ld	temp,Z+		; skip SYN
	mov	u1,txlen
	subi	u1,3		; not over SYN, CRC
	rcall	CRCMessage
	SetZPtr	TxBuf
	mov	u1,txlen
	subi	u1,2
	add	ZL,u1
	ldi	temp,0
	adc	ZH,temp
	st	Z+,CRCHi
	st	Z,CRCLo
	pop	u1
	ret
	
; protocol
;
;msg :
; 0x00	: echo
; 0x01	: read measurements
; 0x02	: read config
; 0x03  : read settings
; 0x04  : 
; 0x05	: 
; 0x06	: 
;
; 0x10	: set Div27
; 0x11	: Set Div15
; 0x12	: Set SP1
; 0x13	: //ErrorCode
; 0x14	: set DAC
; 0x15	: set SP2
; 0x16	: set SP3
; 0x17	: set SP4
; 0x18	: set Latch1
; 0x19	: set Latch2
;
; 0x20	: DeviceID     (write)
; 0x21	: Mode         (write)
; 0x22	: Saveall  (reg to EEProm)
; 0x23  : load FPGA from Memory (new V2.1a)
; 0x24  : load Userparameter1 (newV2.5)
 
; 0x30	: userstring   (write)
;
; 0x40	: devicestring (read)
; 0x41	: serial       (read)
; 0x42	: copyright    (read)
; 0x43	: reference    (read)
; 0x44	: userstring   (read)  
;

comloop:	; master-slave
;	ldi	temp,0x00	;debug
;	out	UDR,temp
	
	cpi	comstate,0x0F
	brne	clend_1
; message received - rxptr = len = 1 byte after last
;  calc crc
	SetZPtr	RxBuf
	mov	u1,rxptr
	subi	u1,2		; exclude CRC itself
	rcall	CRCMessage
	mov	u2,rxptr
	subi	u2,2		; exclude CRC itself
	SetZPtr	RxBuf
	add	ZL,u2
	clr	temp
	adc	ZH,temp
	ld	u1,Z+		;crchi
	ld	u2,Z		;crclo
;	rjmp	dskip	;*****
	cp	crclo,u2
	brne	clend_2		; fail - discard
	cp	crchi,u1
	brne	clend_2		; fail - discard
; test DST ID 
dskip:	;*****
	SetZPtr	RxBuf		; DST at Rxbuf+3
	ldd	u1,Z+3
	ldd	u2,Z+4		; cmd at RxBuf+4
	SetZPtr	DeviceID
	ld	u3,Z
	cp	u1,u3
	breq	cl0		; match
; not equal - pass only 'change ID'=0x20 at DST=0xFF
	cpi	u1,0xff
	brne	clend_2
	cpi	u2,0x20
	brne	clend_2
	rjmp	cl0
clend_2:
;	rcall	ping
;	ldi	temp,1
;	mov	DST,temp
;	ldi	temp,0
;	mov	SRC,temp
;	ldi	temp,0
;	mov	cmd,temp
;	ldi	temp,10
;	mov	txlen,temp
;	rcall	SetupTxFrame
;	st	Z+,crchi
;	st	Z+,crclo
;	rcall	AddCRC
;	rcall	SetupTx
;	rcall	SetupRx
	rjmp	clnone
	
; test msg
cl0:
	SetZPtr	RxBuf
	ldd	U1,Z+2		; copy SRC
	mov	SRC,U1
	ldd	U1,Z+3		; copy DST
	mov	DST,U1
	ldd	U1,Z+4		; get cmd
	mov	Cmd,u1
	cpi	U1,0x00
	brne	cl1
; msg 0x00 - Echo
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
clend_1:
	rjmp	clend	
cl1:
	cpi	U1,0x01
	brne	cl2
; msg 0x01 - measurements
	ldi	temp,measbytes+8
	mov	txlen,temp
	rcall	SetupTxFrame
	SetXPtr	ADC0
	ldi	U2,measbytes	;20 bytes data
	rcall	Copybuf
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx

	rjmp	clend
cl2:
	cpi	U1,0x02
	brne	cl3
; msg 0x02 - config
	ldi	temp,CurrentConfigSize+9  ; adjustable
	mov	txlen,temp
	rcall	SetupTxFrame
	SetXPtr	Configsize
	ldi	U2,CurrentConfigSize	;# bytes data
	inc	U2			; include configsize byte
	rcall	Copybuf
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl3:
	cpi	U1,0x03
	brne	cl4
; msg 0x03 - settings
	ldi	temp,settingbytes+8
	mov	txlen,temp
	rcall	SetupTxFrame
	SetXPtr	BurstADC
	ldi	U2,settingbytes	;# bytes data
	rcall	Copybuf
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl4:
	cpi	U1,0x04
	brne	cl5
; msg 0x04 

	rjmp	clend

cl5:
	cpi	U1,0x05
	brne	cl6
; msg 0x05 

	rjmp	clend		
cl6:
	cpi	U1,0x06
	brne	cl7
; msg 0x06 

	rjmp	clend
cl7:

cl10:
	cpi	U1,0x10
	brne	cl11
; msg 0x10 - set Div27 *************
	SetYPtr T27
	ldd	temp,Z+5
	st	Y+,temp
	ldd	temp,Z+6
	st	Y+,temp
	ldd	temp,Z+7
	st	Y+,temp
	ldd	temp,Z+8
	st	Y,temp
	rcall	load27bit
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl11:
	cpi	U1,0x11
	brne	cl12
; msg 0x11 - set Div15 ************
	SetYPtr T15
	ldd	temp,Z+5
	st	Y+,temp
	ldd	temp,Z+6
	st	Y,temp
	rcall	load15bit
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl12:
	cpi	U1,0x12
	brne	cl13
; msg 0x12 - set SP1 **************
	SetYPtr SP1
	ldd	temp,Z+5
	st	Y+,temp
	rcall	loadsp1
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl13:

cl14:
	cpi	U1,0x14
	brne	cl15
; msg 0x14 - set DAC
;	ldd	temp,Z+5
;	SetYPtr	DAC
;	st	Y,temp
;	rcall	SetDAC
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend		
cl15:
	cpi	U1,0x15
	brne	cl16
; msg 0x15 - set SP2 **************
	SetYPtr SP2
	ldd	temp,Z+5
	st	Y+,temp
	rcall	loadsp2
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl16:
	cpi	U1,0x16
	brne	cl17
; msg 0x16 - set SP3 **************
	SetYPtr SP3
	ldd	temp,Z+5
	st	Y+,temp
	rcall	loadsp3
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl17:
	cpi	U1,0x17
	brne	cl18
; msg 0x17 - set SP4 ***************
	SetYPtr SP4
	ldd	temp,Z+5
	st	Y+,temp
	rcall	loadsp4
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl18:
	cpi	U1,0x18
	brne	cl19
; msg 0x18 - set Latch1 ************
	SetYPtr Latch1
	ldd	temp,Z+5
	st	Y+,temp
	rcall	loadlatch1
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl19:
	cpi	U1,0x19
	brne	cl1A
; msg 0x19 - set Latch2 **********
	SetYPtr Latch2
	ldd	temp,Z+5
	st	Y+,temp
	rcall	loadlatch2
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl1a:
	cpi	U1,0x1a
	brne	cl1b
;msg 0x1a - set pulseblock
	SetYPtr SP1
	ldd	temp,Z+5	;sp1
	st	Y+,temp
	ldd	temp,Z+6	;sp2
	st	Y+,temp
	ldd	temp,Z+7	;sp3
	st	Y+,temp
	ldd	temp,Z+8	;sp4
	st	Y+,temp
	ldd	temp,Z+9	;latch1
	st	Y+,temp
	ldd	temp,Z+10	;latch2
	st	Y,temp
	rcall	loadpulseblock
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend

cl1b:

cl20:
	cpi	U1,0x20
	brne	cl21
; msg 0x20 - deviceID
	ldd	temp,Z+5
	SetYPtr DeviceID
	st	Y,temp
	SaveVar	DeviceID,1
	rcall	CopyRxTx
	SetZPtr	TxBuf
	ld	temp,Y		;set new ID
	std	Z+3,temp
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend	
cl21:
	cpi	U1,0x21
	brne	cl22
; msg 0x21 - Mode
	ldd	temp,Z+5
	SetYPtr	Mode
	st	Y,temp
;	SaveVar	Mode,1
	rcall	setmode
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend	
cl22:
	cpi	U1,0x22
	brne	cl23
; msg 0x22 - Save All
	
	SaveVar	Mode,15
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl23:
	cpi	U1,0x23
	brne	cl24
; msg 0x23  - load FPGA from Memory (new V2.1a)
        rcall	load27bit
	rcall	load15bit
	rcall	loadsp1
	rcall	loadsp2
	rcall	loadsp3
	rcall	loadsp4
	rcall	loadlatch1
	rcall	loadlatch2
	rcall	loadUserPara1
; that was it
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend	
cl24:
	cpi	U1,0x24
	brne	cl25
; msg 0x24 - set UserPara1 (new V2.5)
	SetYPtr UserPara1
	ldd	temp,Z+5
	st	Y+,temp
	SaveVar	UserPara1,1     ;(yes, save this parameter)
	rcall	loadUserPara1
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl25:

cl30:
	cpi	U1,0x30
	brne	cl31
; msg 0x30 - write userstring
	ldd	temp,Z+5	; get length of string
	cpi	temp,28
	brsh	cl30s		;skip if longer than 27
	ldi	ZL,0xC0
	ldi	ZH,0
	SetXPtr	RxBuf
	ldi	u1,5
	add	xl,u1
	ldi	u1,0
	adc	xh,u1
	inc	temp		; include length byte
	mov	u1,temp
	rcall	MoveRTE
cl30s:
	rcall	CopyRxTx
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend	
cl31:	

cl40:	cpi	U1,0x40
	brne	cl41
; msg 0x40 - devicestring
	ldi	ZL,0x40
	ldi	ZH,0
	SetXPtr TxBuf
	ldi	temp,6		; move string to [6]
	add	XL,temp
	ldi	temp,0
	adc	XH,temp
	rcall	EStr2RAM
	SetZPtr	TxBuf
	ldd	temp,Z+6	; get length
	subi	temp,-9
	mov	txlen,temp
	rcall	SetupTxFrame
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl41:	
	cpi	u1,0x41
	brne	cl42
; msg 0x41 - serial
	ldi	ZL,0x60
	ldi	ZH,0
	SetXPtr TxBuf
	ldi	temp,6		; move string to [6]
	add	XL,temp
	ldi	temp,0
	adc	XH,temp
	rcall	EStr2RAM
	SetZPtr	TxBuf
	ldd	temp,Z+6
	subi	temp,-9
	mov	txlen,temp
	rcall	SetupTxFrame
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend

cl42:	cpi	u1,0x42
	brne	cl43
; msg 0x42 - copyright
	ldi	ZL,0x80
	ldi	ZH,0
	SetXPtr TxBuf
	ldi	temp,6		; move string to [6]
	add	XL,temp
	ldi	temp,0
	adc	XH,temp
	rcall	EStr2RAM
	SetZPtr	TxBuf
	ldd	temp,Z+6
	subi	temp,-9
	mov	txlen,temp
	rcall	SetupTxFrame
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl43:	
	cpi	u1,0x43
	brne	cl44
; msg 0x43 - reference
	ldi	ZL,0xA0
	ldi	ZH,0
	SetXPtr TxBuf
	ldi	temp,6		; move string to [6]
	add	XL,temp
	ldi	temp,0
	adc	XH,temp
	rcall	EStr2RAM
	SetZPtr	TxBuf
	ldd	temp,Z+6
	subi	temp,-9
	mov	txlen,temp
	rcall	SetupTxFrame
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl44:
	cpi	U1,0x44
	brne	cl45
; msg 0x44 - read userstring
	ldi	ZL,0xC0
	ldi	ZH,0
	SetXPtr	TxBuf
	ldi	temp,6		; move string to [6]
	add	XL,temp
	ldi	temp,0
	adc	XH,temp
	rcall	EStr2RAM
	SetZPtr	TxBuf
	ldd	temp,Z+6
	subi	temp,-9
	mov	txlen,temp
	rcall	SetupTxFrame
	rcall	AddCRC
	rcall	SetupTx
	rcall	SetupRx
	rjmp	clend
cl45:

clnone:
	rcall	setupRx
clend:
	ret

the crc

; this unit calculates the crc over a message or a byte
;
;.........................................................
;PROCEDURE calcCRC(data:BYTE;VAR crc:WORD);
;VAR i:BYTE;
;BEGIN
; FOR i:=0 TO 7 DO
;  BEGIN
;   IF ((data and $01)XOR(crc AND $0001)<>0) THEN
;    BEGIN
;     crc:=crc shr 1;
;     crc:= crc XOR $A001;
;    END
;   ELSE crc:=crc shr 1;
;   data:=data shr 1; 
;  END;
;END;
CRCByte:	; calculates the CRC over the byte CData and
		; updates the CRC
	push	U1
	push	U2
	push	U3
	ldi	U3,8		; 8 times
_clp:
	mov	U1,CData	; CData AND 0x01
	andi	U1,0x01
	mov	U2,CRCLo	; CRCLo AND 0x01
	andi	U2,0x01
	eor	U2,U1		; (CData AND 0x01)XOR(CRCLo AND 0x01)
	brne	_cne
; =0
	clc			; clear carry
	ror	CRCHi		; shift high
	ror	CRCLo		; shift lo
	rjmp	_cn
_cne: ;<>0
	clc			; clear carry
	ror	CRCHi		; shift high
	ror	CRCLo		; shift lo
	ldi	U1,0xA0		; CRC:=CRC xor 0xA001
	eor	CRCHi,U1
	ldi	U1,0x01
	eor	CRCLo,U1
_cn:	lsr	CData		;data:=data shr 1
	dec	U3
	brne	_clp		; loop 8 times
	pop	U3
	pop	U2
	pop	U1
	ret
;
;note : the crc is initialized as zero (0)
;       the crc is calculated over the message without SYN STX
;
;
;stack : 3 push/pop + ret = 5bytes
;..................................................................
;The message is pointed to by Z, the length is in U1
;
;after the op, 
;  the crc is in CRCLo&CRCHi
;  Z points to the next location
;
CRCMessage:
	clr	CRCLo
	clr	CRCHi
_crc1:	ld	Temp,Z+
	mov	CData,Temp
	rcall	CRCByte
	dec	U1
	brne	_crc1
	ret
;
;stack : ret+subcall = 7bytes
;...................................................................





Questions ?
Suggestions?
Feedback ?







sponsored links




AVR index
embedded software pages
home

last updated: 17.feb.07



Copyright (99,2007) Ing.Büro R.Tschaggelar