.include "..\include\2313def.inc" ; DMB90 Interface ; (c)2001 Michael Rothe ; ; This assembler code is for a ATMEL AT90S2313 controller ; use AVRSTUDIO (freeware, can be found at www.atmel.com) ; then use a programmer of your choice to program the controller ; (see www.avrfreaks.net) ; the interface is controlled via RS232 9600,8N1 ; send a 'd' followed by 0a or 0d to start DMB download ; the command characters will be echoed on reception ; then a '+' will be sent to indicate successful DMB detection ; (check is currently disabled, '+' will always be sent) ; then (if indeed a DMB is connected) will follow 2068 bytes ; of download data .ESEG ; EEPROM data .CSEG ; flash/code data rjmp RESET ; RESET handle rjmp EXT_INT0 rjmp EXT_INT1 rjmp TIM1_CAPT rjmp TIM1_COMPA rjmp TIM1_OVF rjmp TIM0_OVF rjmp UART_RXC rjmp UART_DRE rjmp UART_TXC rjmp ANA_COMP .org $00b .def lowtmp = r10 .def rxflag = r12 .def temp = r20 .def rxcnt = r24 .def data = r22 .def cmd = r23 .equ buffer = $80 ; 40 bytes receive buffer .equ MaxRx = 40 .equ IDRB = PD2 .equ IDATA = PD3 .equ IDCLK = PD4 .equ IDCA = PD5 .equ LED = PD6 .equ VDRB = $04 .equ VDATA = $08 .equ VDCLK = $10 .equ VDCA = $20 .equ DMPSIZE = 2068 .equ space = $20 .equ percent = $25 .equ dot = $2e .equ slash = $2f .equ vau = $56 .equ dash = $2d .equ plus = $2b .equ ahh = $41 .equ grad = $df .equ ceh = $43 .equ deh = $44 .equ ohh = $4f .equ peh = $50 .equ erh = $52 .equ teh = $74 .equ ell = $4c .equ colon = $3a STRING1: .db "DMB90 Interface V1.0",0x0d,0x0a,0x00,0x00 ;-------------------------------------------------------------- EXT_INT0: reti EXT_INT1: reti TIM1_CAPT: reti TIM1_COMPA: reti TIM1_OVF: reti TIM0_OVF: reti UART_RXC: push temp in temp, SREG push temp in temp, UDR out UDR, temp ; debug echo cpi temp, $0d ; line end breq UI_2 cpi temp, $0a ; line end breq UI_2 cpi rxcnt, MaxRx ; check for full buffer brsh UI_X rjmp UI_1 UI_2: com rxflag rjmp UI_X UI_1: push XL push XH clr XH ldi XL, buffer add XL, rxcnt st X, temp inc rxcnt pop XH pop XL UI_X: pop temp out SREG, temp pop temp reti UART_DRE: reti UART_TXC: reti ANA_COMP: reti ;----------------------------------------------------------------------- ASC2NIB: ; ASCII-Zeichen in temp in ein Hex-Nibble (0x00..0x0f) umwandeln subi temp, $30 cpi temp, 10 brlo A2N_0 andi temp, $df subi temp, 7 A2N_0: ret ; 1 ms delay (3686 clocks) from rcall DELAY to next instruction DELAY: push r21 push r22 in r21, SREG push r21 ldi r21,194 ldi r22,5 DLOOP: dec r21 brne DLOOP dec r22 brne DLOOP pop r21 out SREG, r21 pop r22 pop r21 ret D10US: push r21 in r21, SREG push r21 ldi r21, 6 D1LOOP: dec r21 brne D1LOOP nop nop pop r21 out SREG, r21 pop r21 ret D100US: push r21 in r21, SREG push r21 ldi r21, 117 D2LOOP: dec r21 brne D2LOOP nop nop pop r21 out SREG, r21 pop r21 ret ; output a 0-terminated string from program memory to the ; serial port (start address in ZH/ZL) SOUTTXT:lpm ; get first byte tst r0 breq XOT adiw ZL,1 mov data, r0 rcall SOUTC rjmp SOUTTXT XOT: ret SOUTC: out UDR, data rcall DELAY ret ;----------------------------------------------------------------------- PUTBYTE: ldi temp, 8 PBL: lsl data ; shift into c flag, starting with bit 7 brcc PB_1 cbi DDRD, IDCA ; SET_DCA_H rjmp PB_2 PB_1: sbi DDRD, IDCA ; SET_DCA_L PB_2: sbi DDRD, IDCLK ; SET_DCLK_L rcall D100US cbi DDRD, IDCLK ; SET_DCLK_H rcall D100US dec temp brne PBL ret GETBYTE: ldi temp, 8 GBL: sbi DDRD, IDCLK ; SET_DCLK_L rcall D100US sec sbis PIND, IDATA clc ror data ; roll c flag into data cbi DDRD, IDCLK ; SET_DCLK_H rcall D100US dec temp brne GBL ret ;----------------------------------------------------------------------- DOWNLOAD: ; init all H in temp, DDRD andi temp, ~(VDRB+VDATA+VDCLK+VDCA) out DDRD, temp ; wait a while ldi temp, 25 DL1: rcall D100US dec temp brne DL1 ; set all to L in temp, DDRD ori temp, (VDRB+VDATA+VDCLK+VDCA) out DDRD, temp ; wait 10us rcall D10US ; set DRB + CLK = H in temp, DDRD andi temp, ~(VDRB+VDCLK) out DDRD, temp ; wait 20 us rcall D10US rcall D10US ; sample DRB in temp, PIND andi temp, VDRB ; there is an error in the C code, the drb check is always ok ; here, the camera was not detected when the check was performed ; therefore we skip the check and assume always ok rjmp DL2 ; breq DL2 ; use this to activate the check code ; if DRB = 1 : no camera, all H, exit in temp, DDRD andi temp, ~(VDRB+VDATA+VDCLK+VDCA) out DDRD, temp ldi data, dash rcall SOUTC ret ; else DL2: ldi data, plus rcall SOUTC ; set DCA = H in temp, DDRD andi temp, ~(VDCA) out DDRD, temp ; wait 10us rcall D10US ; set DATA = H in temp, DDRD andi temp, ~(VDATA) out DDRD, temp ; wait 20us rcall D10US rcall D10US ; set DATA + DRB = L in temp, DDRD ori temp, (VDRB+VDATA) out DDRD, temp ; wait for clk = L DL3: in temp, PIND andi temp, VDCLK brne DL3 ; wait for clk = H DL4: in temp, PIND andi temp, VDCLK breq DL4 ; wait 2.5ms ldi temp, 25 DL5: rcall D100US dec temp brne DL5 ; set DATA + DRB = H in temp, DDRD andi temp, ~(VDRB+VDATA) out DDRD, temp ; wait 150us ldi temp, 15 DL6: rcall D10US dec temp brne DL6 ; putbyte 5A ldi data, $5a rcall PUTBYTE ; wait 300us rcall D100US rcall D100US rcall D100US ; putbyte BB ldi data, $bb rcall PUTBYTE ; wait 300us rcall D100US rcall D100US rcall D100US ; putbyte FF ldi data, $ff rcall PUTBYTE ; set CLK+DCA = H in temp, DDRD andi temp, ~(VDCLK+VDCA) out DDRD, temp ; wait 100us rcall D100US ; wait for clk = H DL7: in temp, PIND andi temp, VDCLK breq DL7 ; wait 1.8ms ldi temp, 18 DL8: rcall D100US dec temp brne DL8 ; loop 1..2068 ldi XH, HIGH(DMPSIZE) ldi XL, LOW(DMPSIZE) ; get byte DL9: rcall GETBYTE ; send serial byte out UDR, data ; wait 150us ldi temp, 15 DLA: rcall D10US dec temp brne DLA sbiw XL, 1 brne DL9 ; set all to H in temp, DDRD andi temp, ~(VDRB+VDATA+VDCLK+VDCA) out DDRD, temp ret ;----------------------------------------------------------------------- EXEC_CMD: ; kommando verarbeiten, statusbytes entsprechend setzen clr XH ldi XL, buffer tst rxcnt brne PC_E rjmp PC_Q ; unexpected end of buffer, quit PC_E: ld cmd, X+ ; first byte is command andi cmd, $df ; Upcase PC_0: cpi cmd, deh ; 'D' = DOWNLOAD brne PC_1 ; not D rjmp PC_X ; proceed with command execution PC_1: cpi cmd, ell ; 'L' = Toggle LED brne PC_2 ; not L rjmp PC_X ; proceed with command execution PC_2: cpi cmd, vau ; 'V' = Get Version brne PC_Q ; unknown command, quit rjmp PC_X ; proceed with command execution ; dec rxcnt ; brne PC_5 ; unexpected end of buffer, quit ; rjmp PC_Q ;PC_5: ld temp, X+ ; second byte is relais address ; rcall ASC2NIB ; convert from ASCII-Hex nibble to value ; cpi temp, MinRel ; range check ; brlo PC_Q ; cpi temp, MaxRel ; range check ; brsh PC_Q ; relnum invalid, out of range, quit ; nächstes Kommando ausfuehren PC_X: cpi cmd, deh ; 'D' = DOWNLOAD brne PC_X1 ; Kommando 'D' ausfuehren rcall DOWNLOAD ; execute download rjmp PC_Q ; all done, quit ; nächstes Kommando ausfuehren PC_X1: cpi cmd, ell ; 'L' = toggle LED brne PC_X2 ; Kommando 'L' ausfuehren ldi temp, 0x40 in lowtmp, PORTD eor lowtmp, temp out PORTD, lowtmp brne PC_Q ; nächstes Kommando ausfuehren PC_X2: cpi cmd, vau ; 'V' = get Version brne PC_Q ; wait 1ms rcall DELAY ; send version message ldi ZL, LOW(STRING1*2) ldi ZH, HIGH(STRING1*2) rcall SOUTTXT ; Ende (ach was...) PC_Q: ret ; ------------------------------------------------------ ; main entry ; ------------------------------------------------------ RESET: cli ldi temp, LOW(RAMEND) out SPL, temp sei ldi temp, $17 ; 9600 bps out UBRR, temp ldi temp, $98 ; rxint/rx/tx enabled out UCR, temp ldi temp, $40 out PORTD, temp ldi temp, $40 out DDRD, temp ldi temp, $ff out DDRB, temp ldi temp, $00 out PORTB, temp MAINLOOP: tst rxflag breq MAINLOOP clr rxflag ldi temp, 100 ML1: rcall DELAY dec temp brne ML1 rcall EXEC_CMD clr rxcnt rjmp MAINLOOP