.include "m161def.inc" .NOLIST .LIST ;setup stack LDI R16, HIGH(RAMEND) ; Upper byte OUT SPH,R16 ; to stack pointer LDI R16, LOW(RAMEND) ; Lower byte OUT SPL,R16 ; to stack pointer .equ data_port = PORTA .equ data_ddr = DDRA .equ addr_port = PORTC ;--ad pins-- .equ ad_con1 = portb .equ ad_con2 = portd .equ ad_1busy = 6 ;(con1) .equ ad_1rd = 7 ;(con1) 1 .equ ad_2cs = 2 ;(con2) 1 .equ ad_2conv = 3 ;(con2) 1 ;--mem pins-- .equ mem_con = portd .equ mem_we = 5 ;1 .equ mem_oe = 6 ;1 .equ mem_cs = 7 ;1 .equ mem_latch = 4 ;0 ;--camera pins-- .equ cam_con = portb .equ cam_start = 0 ;0 .equ cam_sin = 1 ;0 .equ cam_load = 2 ;0 .equ cam_rst = 3 ;0 .equ cam_xck = 4 ;0 .equ cam_read = 5 ;--reg variables-- .def mem_page = r15 .def mem_addr = r14 .def stat = r13 .def x_pos = r12 .def y_pos = r11 .def AL = r0 .def AM = r1 .def AH = r2 .def BL = r3 .def BM = r4 .def BH = r5 ;--sram variables-- ;.equ mem_page = 0x60 ;------setup initial port directions and values------ sbi ad_con1,ad_1rd sbi ad_con2,ad_2cs sbi ad_con2,ad_2conv sbi DDRB,ad_1rd sbi DDRD,ad_2cs sbi DDRD,ad_2conv sbi mem_con,mem_we sbi mem_con,mem_oe sbi mem_con,mem_cs cbi mem_con,mem_latch sbi DDRD,mem_we sbi DDRD,mem_oe sbi DDRD,mem_cs sbi DDRD,mem_latch sbi DDRB,cam_start sbi DDRB,cam_sin sbi DDRB,cam_load sbi DDRB,cam_rst sbi DDRB,cam_xck cbi DDRB,cam_read ldi r16,255 ;address as output out DDRC,r16 ;------setup UART----------------------------- ldi r16, 0x18 out UCSR0B,r16 ldi r16,8 out UBRR0,r16 ;baud 56000 ;------latch--------------------------------- ldi r16,0 out addr_port,r16 sbi mem_con,mem_latch cbi mem_con,mem_latch ldi r16,100 mov BL,r16 ldi r16,2 mov BM,r16 ldi r16,100 mov BH,r16 ldi r16,100 mov AL,r16 ldi r16,0 mov AM,r16 ldi r16,50 mov AH,r16 ldi r16, 200 ; call sub_B_r16 ; call send_grid call delay_1ms ; call take_pic ; call find_xy_grid_new_max call find_xy_grid call delay_1ms call delay_1ms call delay_1ms call delay_1ms call delay_1ms call delay_1ms ; call find_y ;call find_x rx_wait: sbis UCSR0A,RXC0 rjmp rx_wait ;-------MAIN------------------ call Init_cam loop: ;call Init_cam ;clr mem_page ;clr mem_addr ;call set_page ;out addr_port,mem_addr ldi r16,0 ;take pic 1.1 mov stat,r16 call take_pic ldi r16,1 ;find xy 2 mov stat,r16 call find_xy_grid call send_grid ldi r16,2 ;take pic 1.2 mov stat,r16 call take_pic ldi r16,1 ;take pic 2.1 mov stat,r16 call take_pic ldi r16,0 ;find xy 1 mov stat,r16 call find_xy_grid call send_grid ldi r16,3 ;take pic 2.2 mov stat,r16 call take_pic ;call find_x ;call find_y ;call find_xy_grid ;call pic_rs232 ;call find_x ;call send_grid ;ldi r16,4 ;add x_pos,r16 ;mov r16,x_pos ;call TX ;mov r16,y_pos ;call TX ;mov r16,AL ;call TX ;mov r16,AM ;call TX ;'mov r16,AH ;'call TX ;call pic_rs232 rjmp loop send_b: mov r16,BL call TX mov r16,BM call TX mov r16,BH call TX ret ;-- send_grid: push r17 ldi r17,192 clr YH ldi YL,0x60 send_grid_loop: ld r16,Y+ call TX dec r17 brne send_grid_loop pop r17 ret add_B_r16: clr r31 add BL,r16 adc BM,r31 adc BH,r31 ret sub_B_r16: clr r31 sub BL,r16 sbc BM,r31 sbc BH,r31 ret comp_A_B: cp AH,BH brne comp_A_B_end cp AM,BM brne comp_A_B_end cp AL,BL comp_A_B_end: ret ;----------------------------------------------------------------------- ;find_xy_grid ;purpose: find x and y by splitting into 8x8 grid ;Takes: ;Give: find_xy_grid: push r20 push r19 push r18 push r17 push r16 clr BL clr BM clr BH clr AH clr AM clr AL clr YH ldi YL,0x60 clr mem_page clr mem_addr ldi r16,128 sbrc stat,0 mov mem_addr,r16 ;select correct range call set_page ldi r16,0 out data_ddr,r16 sbi ad_con2,ad_2cs sbi ad_con1,ad_1rd cbi mem_con,mem_cs ;read memory cbi mem_con,mem_oe clr r19 clr r20 clr r17 clr r18 clr r31 ;clr x_pos ;clr y_pos find_xy_grid_loop_block: in r16,PINA ;read value add BL,r16 adc BM,r31 adc BH,r31 inc mem_addr out addr_port,mem_addr inc r18 sbrs r18,4 ;do 16 times rjmp find_xy_grid_loop_block ldi r18,16 sub mem_addr,r18 inc mem_page call set_page clr r18 inc r17 sbrs r17,4 ;do 16 times rjmp find_xy_grid_loop_block st Y+,BL st Y+,BM st Y+,BH call comp_A_B ;compare A and B to see which is bigger brlo find_xy_grid_new_max find_xy_grid_new_max_ret: inc r19 ;inc x grid counter clr r18 clr r17 clr BL clr BM clr BH ldi r16,16 sub mem_page,r16 add mem_addr,r16 call set_page sbrs r19,3 ;get to end of row rjmp find_xy_grid_loop_block clr r19 clr mem_addr ldi r16,128 sbrc stat,0 mov mem_addr,r16 ldi r16,16 add mem_page,r16 call set_page inc r20 ;inc y grid counter sbrs r20,3 ;end of columbs rjmp find_xy_grid_loop_block sbi mem_con,mem_cs sbi mem_con,mem_oe pop r16 pop r17 pop r18 pop r19 pop r20 ret find_xy_grid_new_max: mov AL,BL ;copy to current max mov AM,BM mov AH,BH ldi r16,30 cp BM,r16 brlo humm ;skip 2 instructions if lower mov x_pos,r19 mov y_pos,r20 humm: rjmp find_xy_grid_new_max_ret ;----------------------------------------------------------------------- ;find_x ;purpose: find x of max movement ;Takes: ;Give: find_x: push r19 push r18 push r17 push r16 clr r0 clr r1 clr r2 clr r3 clr r4 clr r5 clr mem_page clr mem_addr call set_page out addr_port,mem_addr ldi r16,0 out data_ddr,r16 sbi ad_con2,ad_2cs sbi ad_con1,ad_1rd cbi mem_con,mem_cs ;read memory cbi mem_con,mem_oe clr r17 clr r18 clr r31 find_x_start_loop: in r16,PINA ;read value ;call add_B_r16 ;add value to B add BL,r16 adc BM,r31 adc BH,r31 inc mem_addr out addr_port,mem_addr inc r18 sbrs r18,4 ;do 16 times rjmp find_x_start_loop ldi r18,16 sub mem_addr,r18 inc mem_page call set_page clr r18 sbrs mem_page,7 ;do 128 times rjmp find_x_start_loop ;put max here mov AL,BL ;copy to current max mov AM,BM mov AH,BH ; call send_b ;clr x_pos clr mem_page clr mem_addr clr r17 clr r18 ldi r19, 16 find_x_main_loop: in r16,PINA ;read value ;call sub_B_R16 sub BL,r16 sbc BM,r31 sbc BH,r31 add mem_addr,r19 ;add 16 out addr_port,mem_addr nop in r16,PINA ;read value ;call add_B_R16 add BL,r16 adc BM,r31 adc BH,r31 sub mem_addr,r19 ;-16 inc mem_page ;call set_page out addr_port,mem_page ;change addr port sbi mem_con,mem_latch ;latch it cbi mem_con,mem_latch out addr_port,mem_addr sbrs mem_page,7 ;do 128 times rjmp find_x_main_loop ; call send_b inc mem_addr call comp_A_B ;compare A and B to see which is bigger brlo find_x_new_max find_x_new_max_ret: clr mem_page call set_page mov r17,mem_addr cpi r17,111 breq find_x_main_loop_exit rjmp find_x_main_loop find_x_main_loop_exit: sbi mem_con,mem_cs sbi mem_con,mem_oe pop r16 pop r17 pop r18 pop r19 ret find_x_new_max: mov AL,BL ;copy to current max mov AM,BM mov AH,BH ldi r16,1 ;test to see if over 50000 cp BH,r16 brsh find_x_new_max_set ldi r16,0x0 ;a3 cp BM,r16 brsh find_x_new_max_set rjmp find_x_new_max_ret find_x_new_max_set: mov x_pos,mem_addr ;copy new x pos rjmp find_x_new_max_ret ;find_y ;purpose: find x of max movement ;Takes: ;Give: find_y: push r19 push r18 push r17 push r16 clr r0 clr r1 clr r2 clr r3 clr r4 clr r5 clr mem_page mov mem_addr,x_pos call set_page ldi r16,0 out data_ddr,r16 sbi ad_con2,ad_2cs sbi ad_con1,ad_1rd cbi mem_con,mem_cs ;read memory cbi mem_con,mem_oe clr r17 clr r18 clr r31 find_y_start_loop: in r16,PINA ;read value ;call add_B_r16 ;add value to B add BL,r16 adc BM,r31 adc BH,r31 inc mem_addr out addr_port,mem_addr inc r18 sbrs r18,4 ;do 16 times rjmp find_y_start_loop ldi r18,16 sub mem_addr,r18 inc mem_page call set_page clr r18 sbrs mem_page,4 ;do 16 times rjmp find_y_start_loop mov AL,BL ;copy to current max mov AM,BM mov AH,BH clr mem_page mov mem_addr,x_pos call set_page clr r17 clr r18 ldi r19, 16 find_y_main_loop: in r16,PINA ;read value sub BL,r16 sbc BM,r31 sbc BH,r31 add mem_page,r19 ;add 16 call set_page nop in r16,PINA ;read value ;call add_B_R16 add BL,r16 adc BM,r31 adc BH,r31 sub mem_page,r19 ;-16 inc mem_addr ;call set_page out addr_port,mem_page ;change addr port sbi mem_con,mem_latch ;latch it cbi mem_con,mem_latch out addr_port,mem_addr inc r18 sbrs r18,4 ;do 16 times rjmp find_y_main_loop clr r18 inc mem_page call comp_A_B ;compare A and B to see which is bigger brlo find_y_new_max find_y_new_max_ret: mov mem_addr,x_pos call set_page mov r17,mem_page cpi r17,111 breq find_y_main_loop_exit rjmp find_y_main_loop find_y_main_loop_exit: sbi mem_con,mem_cs sbi mem_con,mem_oe pop r16 pop r17 pop r18 pop r19 ret find_y_new_max: mov AL,BL ;copy to current max mov AM,BM mov AH,BH ldi r16,1 ;test to see if over 50000 cp BH,r16 brsh find_y_new_max_set ldi r16,0x1 cp BM,r16 brsh find_y_new_max_set rjmp find_y_new_max_ret find_y_new_max_set: mov y_pos,mem_page ;copy new x pos rjmp find_y_new_max_ret pic_rs232: clr mem_page clr mem_addr call set_page out addr_port,mem_addr ldi r16,0 out data_ddr,r16 cbi mem_con,mem_cs cbi mem_con,mem_oe clr r17 clr r18 ; rjmp loop pic_rs232_loop: in r16,PINA breq add_one ret_temp: call TX ; call delay_1ms inc mem_addr out addr_port,mem_addr sbrs mem_addr,7 rjmp pic_rs232_loop inc mem_page call set_page clr mem_addr out addr_port,mem_addr sbrs mem_page,7 rjmp pic_rs232_loop ret add_one: inc r16 rjmp ret_temp ;----------------------------------------------------------------------- ;take_pic ;purpose: takes a picture ;Takes: mem_page ;Give: take_pic: push r17 push r18 push r19 push r20 clr mem_page clr mem_addr ldi r16,128 sbrc stat,0 mov mem_addr,r16 ;select correct range call set_page sbi ad_con2,ad_2cs ;setup A/D and mem, so mem reads A/D sbi ad_con1,ad_1rd ;NOTE MAY HAVE TO TOGGLE?? sbi mem_con,mem_oe sbi mem_con,mem_cs ; ldi r16,255 ; out data_ddr,r16 ; ldi r16, 85 ; out data_port,r16 cbi cam_con,cam_xck ;ck low call ckd sbi cam_con,cam_start call ckd sbi cam_con,cam_xck ;ck h call ckd cbi cam_con,cam_xck call ckd cbi cam_con,cam_start take_pic_expose: cbi cam_con,cam_xck ;ck l call ckd sbi cam_con,cam_xck ;ck h call ckd sbis pinb,cam_read rjmp take_pic_expose mov r17,stat sbr r17,0x80 ;interal flag, so next frame knows its first mov stat,r17 clr r17 ;counter clr r18 ;counter2 take_pic_loop: ; cbi cam_con,cam_xck ;ck l ;call ckd nop nop nop cbi ad_con2,ad_2conv ;low pulse (start conversion) sbi ad_con2,ad_2conv sbrc stat,1 ;if stat:1 is set, then subtract frame call frame2 sbrs stat,1 ;if stat:1 is clear, then first frame call frame1 sbi cam_con,cam_xck ;ck h call AD_wait cbi ad_con2,ad_2cs cbi ad_con1,ad_1rd ;clr r16 ;out data_ddr,r16 ;out data_port,r16 ;cbi mem_con,mem_we ;write data to memory ;sbi mem_con,mem_we nop in r19,PINA ;read A/D value ;inc r19 nop ;sbi ad_con1,ad_1rd ;sbi ad_con2,ad_2cs cbi cam_con,cam_xck ;ck l ;sbi cam_con,cam_xck ;ck h ; inc mem_addr ;inc mem address ; out addr_port,mem_addr ;inc r17 sbrs r17,7 ;done 128 times rjmp take_pic_loop clr mem_addr sbrc stat,0 ;if stat:0 is set, then mode 2 mov mem_addr,r17 ;set to 128 inc mem_page call set_page clr r17 sbrs mem_page,7 ;done 128 times rjmp take_pic_loop ;--last pixel-- (missed first pixle) sbrc stat,1 ;if stat:1 is set, then subtract frame call frame2 sbrs stat,1 ;if stat:1 is clear, then first frame call frame1 sbi ad_con2,ad_2cs sbi ad_con1,ad_1rd sbi mem_con,mem_cs ldi r16,0 out data_ddr,r16 pop r20 pop r19 pop r18 pop r17 ret ;----------------------------------------------------------------------- ;frame1 ;purpose: copy frame directly to memory ;Takes: value in r19 ;Give: frame1: sbrc stat,7 ;test if first run though rjmp frame1_exit sbi ad_con2,ad_2cs ;set to write to memory sbi ad_con1,ad_1rd sbi mem_con,mem_oe cbi mem_con,mem_cs ldi r16,255 out data_ddr,r16 out data_port,r19 ;put value onto port nop cbi mem_con,mem_we ;write data to memory sbi mem_con,mem_we nop ldi r16,0 out data_ddr,r16 sbi mem_con,mem_cs inc r17 inc mem_addr ;inc mem address out addr_port,mem_addr frame1_exit: mov r20,stat cbr r20,0x80 ;clear bit, so not first frame mov stat,r20 ret ;----------------------------------------------------------------------- ;frame2 ;purpose: copy find postive differenc (whats that called again?!) of new vlaue and old ;Takes: value in r19 ;Give: frame2: sbrc stat,7 ;test if first run though rjmp frame2_exit sbi ad_con2,ad_2cs ;set to read from memory sbi ad_con1,ad_1rd ldi r16,0 out data_ddr,r16 cbi mem_con,mem_cs cbi mem_con,mem_oe nop ;nop in r20, PINA ;read old value sub r20,r19 brlo frame2_invert frame2_invert_return: sbi mem_con,mem_oe ;mem in ldi r16,255 ;port out out data_ddr,r16 out data_port,r20 nop cbi mem_con,mem_we ;write data to memory sbi mem_con,mem_we nop ldi r16,0 out data_ddr,r16 sbi mem_con,mem_cs inc r17 inc mem_addr ;inc mem address out addr_port,mem_addr frame2_exit: mov r20,stat cbr r20,0x80 ;clear bit, so not first frame mov stat,r20 ret frame2_invert: com r20 rjmp frame2_invert_return ;----------------------------------------------------------------------- ;set_page ;purpose: sets memory page to mem_page ;Takes: mem_page ;Give: set_page: ;push r16 ;in r16, addr_port ;temp store current address out addr_port,mem_page ;change addr port sbi mem_con,mem_latch ;latch it cbi mem_con,mem_latch out addr_port,mem_addr ; pop r16 ret ;----------------------------------------------------------------------- ;Init_cam ;purpose: Initalise camera registers ;Takes: ;Give: Init_cam: call cam_reset clr r17 ldi r16,0 ;z reg call cam_register inc r17 ldi r16,7 call cam_register ;various reg inc r17 ldi r16,5 call cam_register ;exposer1 inc r17 ldi r16,150 call cam_register ;exposer2 inc r17 ldi r16,1 call cam_register ;p reg inc r17 ldi r16,0 call cam_register ;m reg inc r17 ldi r16,1 call cam_register ;x reg inc r17 ldi r16,7 call cam_register ;various (in Vref) ret ;----------------------------------------------------------------------- ;cam_reset ;purpose: Resets Camera ;Takes: ;Give: cam_reset: cbi cam_con,cam_xck ;ck low cbi cam_con,cam_rst ;reset low call ckd sbi cam_con,cam_xck ;ck high call ckd cbi cam_con,cam_xck ;ck low call ckd sbi cam_con,cam_rst ;reset high call ckd ret ;----------------------------------------------------------------------- ;cam_register ;purpose: Sets a register in camera ;Takes: r16 = data, r17 = address ;Give: cam_register: ;sets register, data in r16, add in r17 push ZL push ZH push r18 mov ZH,r17 mov ZL,r16 ldi r18,11 ;init bit counter cbi cam_con,cam_load ;ck load cam_register_loop: call ckd cbi cam_con,cam_xck ;ck low cbi cam_con,cam_sin sbrc ZH,2 ;test bit 2 in upper reg sbi cam_con,cam_sin ;set sin call ckd sbi cam_con,cam_xck ;set clk lsl zl ;zl<1 rol zh ;zh<1