.include "m128def.inc" ;All code written by Emile Belanger ;except:Bin to BCD conversion, taken from http://www.avr-asm-tutorial.net/avr_en/calc/CONVERT.html#bcd2bin ;div8 taken from http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E.html .NOLIST .def posy = r15 .def posx = r14 .def ty = r13 .def tx = r12 ;mouse cordinates ;constants and pins ;--constatns--------- .equ ps2_x_offsetL = 0x20 ;offset constants for pad (1300) .equ ps2_x_offsetH = 0x05 .equ ps2_y_offsetL = 0xdc ;(1500) .equ ps2_y_offsetH = 0x05 .equ ps2_x_div = 31 .equ ps2_y_div = 45 ;-------------------- .equ lcd_con = porta .equ lcd_data = portc .equ lcd_data_ddr = DDRC .equ lcd_data_pin = pinc .equ lcd_di = 4 ;0 .equ lcd_rw = 3 ;0 .equ lcd_e = 2 ;0 .equ lcd_cs1 = 7 ;1 .equ lcd_reset = 6 ;0 .equ lcd_cs2 = 5 ;1 .equ ps2_con = porte .equ ps2_ddr = DDRe ;port direction control .equ ps2_pin = PINe .equ ps2_clk = 6 ;ps2 clock .equ ps2_data = 5 ;ps2 data .equ rf_con = portb ;Rf 433mhz module .equ rf_ddr = DDRb .equ rf_en = 4 .equ rf_data = 5 ;-----variables for basic operation--- .dseg ;--VRAM-------------------- .equ vram = 0x800 ;Video ram .org 0x100 ;.equ block_temp = 0x0060 stat: .BYTE 1 ;status and control byte block_temp: .BYTE 32 ;16 bytes of tempory space temp: .BYTE 16 ;temp space, size = 16 ;.equ tempH = 0 ps2_z: .BYTE 1 ;pressure value ps2_buttons: .BYTE 1 ;buttons pressed ps2_packet: .BYTE 8 ;packet , size = 8 ps2_xL: .BYTE 1 ps2_xH: .BYTE 1 ps2_yL: .BYTE 1 ps2_yH: .BYTE 1 ;--Text Input ram string--- text_ram: .BYTE 64 ;max len = 63 + end chr (chr(255) ;----variables for programs/games start at 0x0100:--- ;pacman .dseg .org 0x400 pac_board: .BYTE 512 ;pacman board ;0=nothing ;1=wall ;2=player ;4=enemy not over food ;8=food ;16=enemy over food ;32=power up pac_objects: .BYTE 64 ;object state table (enemyes, players ect) ;can have 16 objeccts of 4 bytes each(possible expand) pac_no_obs : .BYTE 1 ;number of objects pac_ob_data1: .BYTE 1 pac_ob_data2: .BYTE 1 .cseg rjmp GO ;---INTERUPTS----- .org $0020 jmp Timer0_int ;---start of code-- .org $0046 GO: ;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 call lcd_clear_vram ldi r16,0x40;x mov r8,r16 ldi r16,0x24 mov r9,r16 ldi r16,0x40;y mov r10,r16 ldi r16,0x24 mov r11,r16 ldi r16,0x20;z mov r12,r16 ldi r16,0x2a mov r13,r16 ldi ZL,low(shape_cube<<1) ldi ZH,high(shape_cube<<1) call draw_3d_shape ;call conv_3d ldi r16,0 mov posx,r16 ldi r16,0 mov posy,r16 ldi r24,0 ldi r25,0 ; call lcd_line call delay_1ms ;-----setpu port directions----- ldi r16, 0b10100000 out porta, r16 ldi r16 ,0b11111100 ;set portd directions out DDRA,r16 ldi r16 ,0b00000000 ;portb dir out lcd_data_ddr,r16 cbi ps2_ddr,ps2_clk ;make ps2 inputs cbi ps2_ddr,ps2_data ; sbi rf_ddr,rf_en ;rf as outputs ; sbi rf_ddr,rf_data ;-----setup Timer0 for random nos----- ldi r16,1 out TCCR0,r16 ;-----setup Rs232 -------------------- ldi r16,0x00 out UCSR0B,r16 out UCSR0A,r16 ;out UBRRH,r16 ldi r16,0x86 ;out UCSRC,r16 ldi r16,0x18 out UCSR0B,r16 ldi r16,8 out UBRR0L,r16 cbi rf_con,rf_en ;-----initialise LCD------------ sbi lcd_con,lcd_reset ;un-reset LCD call delay_1ms cbi lcd_con,lcd_cs1 ;select chip1 cbi lcd_con,lcd_cs2 ;select chip2 call delay_1ms ldi r16,0x3f ;display ON call lcd_inst ldi r16,68 ;y=0 call lcd_inst ldi r16,0xb8 ;x=0 call lcd_inst ;-------------------------------- ;----set up timer interupt---- ;use timer int to get samples from pad ldi r16,5 out TCCR0,r16 ldi r16,1 out TIMSK,r16 ;-----test area------------------ call lcd_clear_vram ;rjmp go1 ldi r16,100 mov posx,r16 ldi r16,30 mov posy,r16 ldi r16,1 ;call lcd_pixel ; call lcd_chr ;call lcd_refresh ; call tetris d: ;rjmp d ; call text_input clr r16 sts ps2_buttons,r16 startup: call lcd_clear ldi r16,'S' ;send 'S' out serial port call tx_rs ldi r16,3 mov posy,r16 ldi r16,20 mov posx,r16 ldi r16,'S' call lcd_chr ldi r16,'t' call lcd_chr ldi r16,'a' call lcd_chr ldi r16,'r' call lcd_chr ldi r16,'t' call lcd_chr ldi r16,'u' call lcd_chr ldi r16,'p' call lcd_chr call lcd_refresh go1: ldi r16,255 startup_wait: ; call delay_1ms call delay_1ms call delay_1ms call delay_1ms dec r16 brne startup_wait asd: call ps2_input call ps2_input call ps2_reset ldi r16,0x40;x mov r8,r16 ldi r16,0x24 mov r9,r16 ldi r16,0x40;y mov r10,r16 ldi r16,0x24 mov r11,r16 ldi r16,0x20;z mov r12,r16 ldi r16,0x2a mov r13,r16 ;ldi ZL,low(shape_pyramid<<1) ;ldi ZH,high(shape_pyramid<<1) ldi ZL,low(shape_cube<<1) ldi ZH,high(shape_cube<<1) rjmp pad ;call draw_3d_shape ;call lcd_refresh all: clr r17 ldi r16,50 add r8,r16 adc r9,r17 add r10,r16 adc r11,r17 call lcd_clear_vram call draw_3d_shape call lcd_refresh rjmp all pad: call ps2_get_packet call ps2_process_packet clr r9 clr r11 mov r8,tx mov r10,ty ldi r16,0xc8;z mov r12,r16 ldi r16,0x32 mov r13,r16 lds r16,ps2_z ldi r17,60 mul r17,r16 sub r12,r0 sbc r13,r1 ldi r16,7 www: lsl r8 rol r9 lsl r10 rol r11 dec r16 brne www lsl r10 rol r11 ldi r17,0x19 add r9,r17 add r11,r17 call draw_3d_shape call lcd_refresh call lcd_clear_vram rjmp pad ; ldi r16,0XEA ; call ps2_output ; call ps2_input ; sei ldi r16,0 mov posx,r16 ldi r16,0 mov posy,r16 ldi r24,63 ldi r25,63 rjmp draw ;call lcd_refresh ldi r16,1 ldi r17,128 lright: ;call frame_delay ;call delay_1ms ;call delay_1ms ;call delay_1ms call lcd_clear_vram call lcd_line call lcd_refresh inc posx ldi r17,128 cp posx,r17 brne lright lleft: call lcd_clear_vram call lcd_line call lcd_refresh dec posx brne lleft rjmp lright call pacman call text_input ; ldi r16,0XF4 ; call ps2_output ; call ps2_input ;rjmp l ;call text_input ; call pacman ; call text_input ; sei ; brne test ;k: ; jmp k ; rjmp l draw: clr posx clr posy clr r24 clr r25 draw_loop: call ps2_get_packet call ps2_process_packet movw posx,tx ldi r16,1 call lcd_line movw r24,posx ;copy old pos call lcd_refresh call delay_1ms call delay_1ms rjmp draw_loop display_cords: push posx push posy push r16 push r17 push YL push YH call ps2_get_packet call ps2_process_packet mov r16,tx clr r17 call Bin2ToBcd5 ldi YH,HIGH(temp) ldi YL,LOW(temp) clr posx clr posy ldi r17,48 ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr mov r16,ty clr r17 call Bin2ToBcd5 ldi YH,HIGH(temp) ldi YL,low(temp) clr posx clr posy inc posy ldi r17,48 ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr lds r16,ps2_z clr r17 call Bin2ToBcd5 ldi YH,HIGH(temp) ldi YL,LOW(temp) clr posx clr posy inc posy inc posy ldi r17,48 ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr ld r16,Y+ add r16,r17 call lcd_chr ; call ps2_tx_packet pop YH pop YL pop r17 pop r16 pop posy pop posx rjmp display_cords: call lcd_clear ;call pacman call delay_1ms call delay_1ms ldi r16,10 mov posx,r16 ldi r16,1 mov posy,r16 ldi r16,'E' call lcd_chr ldi r16,'m' call lcd_chr ldi r16,'i' call lcd_chr ldi r16,'l' call lcd_chr ldi r16,'e' call lcd_chr ldi r16,' ' call lcd_chr ldi r16, 'B' call lcd_chr ldi r16, 'e' call lcd_chr ldi r16, 'l' call lcd_chr ldi r16, 'a' call lcd_chr ldi r16, 'n' call lcd_chr ldi r16, 'g' call lcd_chr ldi r16, 'e' call lcd_chr ldi r16, 'r' call lcd_chr ldi r16,3 ;call lcd_block4 nop nop pacman: ;setup and start game call lcd_clear call pac_get_board call pac_paint_board ;we: rjmp we ldi r16,5 sts pac_no_obs,r16 ldi YL,LOW(pac_objects) ldi YH,HIGH(pac_objects) ldi r16,255 ;following sets up ememy start locations ect. st Y+,r16 ldi r16,255 st Y+,r16 ldi r16,25 ;x=3, type1 st Y+,r16 ldi r16,17 ;y=1, dir = 1 st Y+,r16 ;--- ldi r16,255 st Y+,r16 ldi r16,100 st Y+,r16 ldi r16,241 ;x=30, type1 st Y+,r16 ldi r16,39 ;y=1, dir = 2 st Y+,r16 ;-- ldi r16,255 st Y+,r16 ldi r16,80 st Y+,r16 ldi r16,145 ;x=30, type1 st Y+,r16 ldi r16,39 ;y=1, dir = 2 st Y+,r16 ;-- ldi r16,255 st Y+,r16 ldi r16,20 st Y+,r16 ldi r16,145 ;x=30, type1 st Y+,r16 ldi r16,40 ;y=1, dir = 2 st Y+,r16 ;-- ldi r16,255 st Y+,r16 ldi r16,200 st Y+,r16 ldi r16,145 ;x=30, type1 st Y+,r16 ldi r16,39 ;y=1, dir = 2 st Y+,r16 ;----------------------------------------------------------------------- ;pac_main_loop ;purpose: Pacman Game! ;Takes: your time ;Give: an excellent game pac_main_loop: ;game loop ldi YL,LOW(pac_objects) ldi YH,HIGH(pac_objects) lds r16,pac_no_obs ;will perform frame loop for the number of objects in game pac_frame_loop: ld r17,Y+ ld r18,Y+ ld r19,Y+ sts pac_ob_data1,r19 ld r19,Y+ sts pac_ob_data2,r19 sub r17,r18 ;there is an overflow, do object task brcs pac_do_object pac_frame_loop_return: lds r19,pac_ob_data2 ;store back new values st -Y,r19 lds r19,pac_ob_data1 st -Y,r19 st -Y,r18 ;retunred from doing object stuff st -Y,r17 ;store back modified stage value ld r17,Y+ ld r17,Y+ ld r17,Y+ ld r17,Y+ dec r16 ;dec object number brne pac_frame_loop call frame_delay ;sets the overall speed of the frames ;call frame_delay ;sets the overall speed of the frames call lcd_refresh rjmp pac_main_loop ;----------------------------------------------------------------------- ;pac_do_object ;purpose: called if it is objects times to perform action, eg enemy move ;Takes: ;Give: pac_do_object: push r16 push r17 push r18 push r19 push YL push YH ; st -Y,r18 ;store back ; st -Y,r17 ;store back modified stage value ; ld r16,Y+ ; ld r16,Y+ lds r17,pac_ob_data1 andi r17,7 ;mask off tope 5 bits, object type is store in bottom 3 clr r16 ;NOTE: must be a better way of doing this ;..done because branch inst only got +-64 places cp r16,r17 breq pac_do_object0 ;object is player inc r16 cp r16,r17 breq pac_do_object1 ;object is enemy inc r16 ;should have branched by now....:$ pac_do_object0: rjmp pac_ob_player pac_do_object1: rjmp pac_ob_enemy ;----------------------------------------------------------------------- ;pac_ob_player ;purpose: players turn to move ;Takes: ;Give: pac_ob_player: pop YH pop YL pop r19 pop r18 pop r17 pop r16 rjmp pac_frame_loop ;----------------------------------------------------------------------- ;pac_ob_enemy ;purpose: players turn to move ;Takes: ;Give: pac_ob_enemy: lds r16,pac_ob_data2 ;load object data 2 sbrc r16,7 ;if state bit 4 is set, then ememy in 'hunt' mode rjmp pac_ob_enemy_hunt ;else in 'wander' mode ;start of 'wander' mode code swap r16 ;setup to read current direction andi r16,3 call pac_ob_enemy_test_new_dir ;test to see if can go another way but forwards lds r18,pac_ob_data2 ;get ypos andi r18,15 mov posy,r18 lds r18,pac_ob_data1 ;get xpos lsr r18 lsr r18 lsr r18 mov posx,r18 mov r18,r16 ;make copy of dir ldi r16,0 ;blank space call lcd_block4 ;ldi YL,LOW(pac_objects) ;ldi YH,HIGH(pac_objects) cpi r18,0 breq t1 cpi r18,1 breq t2 cpi r18,2 breq t3 cpi r18,3 breq t4 pac_ob_enemy_finish: swap r18 ;writeing back new data values (direction) or r18,posy ;wirte y value sts pac_ob_data2,r18 mov r18,posx lsl r18 lsl r18 lsl r18 sbr r18,1 ;set to type "1" sts pac_ob_data1,r18 ldi r16,4 ;enemy call lcd_block4 pop YH pop YL pop r19 pop r18 pop r17 pop r16 rjmp pac_frame_loop_return t1: dec posy rjmp pac_ob_enemy_finish t2: inc posx rjmp pac_ob_enemy_finish t3: inc posy rjmp pac_ob_enemy_finish t4: dec posx rjmp pac_ob_enemy_finish ;----------------------------------------------------------------------- ;pac_ob_enemy_test_new_dir ;purpose: tests if there is a wall either side of direction of travle (ie hole in wall) ;Takes: r16, direction, and object data ;Give: possible new direction in r16 pac_ob_enemy_test_new_dir: in r17,TCNT0 mov r19,r16 ;make copy of r16 mov r18,r17 andi r18,3 ;just get 2 bottom bits clr r22 ;counter pac_ob_enemy_test_new_dir_loop: sbrc r17,3 ;test 3rd bit of random number to decide direction rotation inc r18 ;clockwise sbrs r17,3 ;test 3rd bit of random number to decide direction rotation dec r18 sbrc r18,7 ;check not under 0..if it is then back to 3 ldi r18,3 sbrc r18,2 ;check not over 3..if it is then back to 0 ldi r18,0 mov r16,r18 call pac_ob_enemy_test_dir ldi r20,1 ;(wall) cpse r18,r19 ;test if the same, if same then.. rjmp temp9382 mov r21,r20 ;make r17 a wall anyway temp9382: sbrc r22,2 ;..then enemy is stuck ldi r18,4 ;make r18 illegal dir 4, sbrc r22,2 ldi r21,0 ;make sure exits loop inc r22 ;safty counter..if done loop over 4 times cp r21,r20 ;test not wall breq pac_ob_enemy_test_new_dir_loop mov r17,r18 ;copy r18 ldi r20,2 ;this 'unreverses' the direction in r18 sub r18,r20 andi r18,3 sbrc r17,2 ;test to see if r18 was 4 rjmp temp3425 mov r16,r18 ret temp3425: ; mov r16,r18 ; call pac_ob_enemy_test_dir ; ldi r20,1 ;(wall) ; cp r21,r20 lds r16,pac_ob_data2 ;load object data 2 swap r16 ;setup to read current direction andi r16,3 ldi r17,2 ;this reverses the direction in r16 sub r16,r17 andi r16,3 ret ;----------------------------------------------------------------------- ;pac_ob_enemy_test_dir ;purpose: ;Takes: ;Give: pac_ob_enemy_test_dir: push r18 push r19 push YL push YH ldi YL,LOW(pac_board) ldi YH,HIGH(pac_board) lds r18,pac_ob_data2 ;get ypos andi r18,15 ldi r19,32 ;line offset mul r18,r19 lds r18,pac_ob_data1 ;get xpos lsr r18 lsr r18 lsr r18 add r0,r18 ;table offset is now in r1:r0 add YL,r0 ;Y now at postion of object adc YH,r1 cpi r16,2 ;note: have been reversed! breq Ysub32 cpi r16,3 breq Yadd1 cpi r16,0 breq Yadd32 cpi r16,1 breq Ysub1 pac_ob_enemy_test_dir_ret: ld r21,Y pop YH pop YL pop r19 pop r18 ret ;--- Ysub32: subi YL,32 rjmp pac_ob_enemy_test_dir_ret Yadd32: adiw YL,32 rjmp pac_ob_enemy_test_dir_ret Yadd1: adiw YL,1 rjmp pac_ob_enemy_test_dir_ret Ysub1: subi YL,1 rjmp pac_ob_enemy_test_dir_ret ;--- pac_ob_enemy_hunt: rjmp pac_ob_enemy_finish ;----------------------------------------------------------------------- ;pac_get_board ;purpose: get board layout from prog mem and put into sram ;Takes: ;Give: pac_get_board: push r16 push r17 push r18 push r19 ldi YL,LOW(pac_board) ldi YH,HIGH(pac_board) ldi ZH,high(pac_board_mem<<1) ldi ZL,low(pac_board_mem<<1) ;setup Z for block access ldi r16,1 clr r17 pac_get_board_loop: lpm r18,Z+ clr r19 pac_get_board_loop1: sbrc r18,0 ldi r16,1 ;bit is "1",so load 16 with "wall" variable sbrs r18,0 ldi r16,2 ;bit is "0",so load 16 with "food" variable st Y+,r16 lsr r18 inc r19 sbrs r19,3 ;do 8 times rjmp pac_get_board_loop1 inc r17 sbrs r17,6 ;do 64 times rjmp pac_get_board_loop pop r19 pop r18 pop r17 pop r16 ret ;----------------------------------------------------------------------- ;pac_paint_board ;purpose: paint board data into lcd ;Takes: ;Give: pac_paint_board: push r16 push YL push YH ldi YL,LOW(pac_board) ldi YH,HIGH(pac_board) clr posy pac_paint_board_loop: clr posx pac_paint_board_loop1: ld r16,Y+ ;ldi r16,3 call lcd_block4 inc posx sbrs posx,5 ;32 times rjmp pac_paint_board_loop1 inc posy sbrs posy,4 ;16 times rjmp pac_paint_board_loop pop YH pop YL pop r16 ret ;----------------------------------------------------------------------- ;text_input ;purpose: goes into text input mode ;Takes: r16=chr to put, posx, posy ;Give: chr on lcd, also inc posx text_input: push r0 push r1 push r2 ;old selected character push r3 push r16 push r17 push r18 push r19 push r20 push r21 clr r16 ;call lcd_clear call text_input_draw_screen ldi r16,50 mov posx,r16 clr posy inc posy ;call lcd_inv_textinput inc posy ; call lcd_inv_textinput stop: ;rjmp stop ;call lcd_clear clr r2 clr posx clr posy call lcd_inv_textinput inc posy call lcd_inv_textinput ; sei ;int on text_input_loop: nop nop mov posx,tx mov posy,ty ldi r16,4 ; call lcd_pixel call ps2_get_packet call ps2_process_packet lds r19,ps2_buttons sbrs r19,5 ;test if finger on pad.. rjmp text_input_loop ; cli ;int off movw r20,tx ;copy x,y locations to r19 and r20 mov r16,r20 clr r17 ldi r18,26 call div8 ;divide pos x by 13 get range 0-4 mov r20,r16 mov r16,r21 ;get y and dived by 16, gives range 0-3 lsr r16 lsr r16 lsr r16 lsr r16 ldi r17,8 ;number of chars per line(acctually 5, but make easier calcs) mul r17,r16 add r0,r20 ;finds currently selected chr mov r3,r0 ;new chr cp r2,r3 ;compares new value with old, if different, then branch brne text_input_change rjmp text_input_loop text_input_change: mov r19,r2 ;un-invert last pos andi r19,0b00000111 ;find x ldi r17,26 mul r17,r19 mov posx,r0 lsr r2 ;find y lsr r2 lsr r2 mov r17,r2 andi r17,0b00000111 lsl r17 ;X2 mov posy,r17 call lcd_inv_textinput inc posy call lcd_inv_textinput ldi r17,26 ;invert new pos mul r17,r20 mov posx,r0 lsl r16 ;x2 mov posy,r16 ;y pos call lcd_inv_textinput inc posy call lcd_inv_textinput mov r2,r3 ;copy new value to old value call lcd_refresh rjmp text_input_loop ;----------------------------------------------------------------------- ;text_input_draw_screen1 ;purpose: draws text input screen 2(normal alpha chrs) ;Takes: SCREEN TO DRAW IN R16 ;Give: text_input_draw_screen: push ZH push ZL push r16 push r17 push r18 push r19 ldi ZH,HIGH(text_input_screens<<1) ldi ZL,LOW(text_input_screens<<1) ldi r17,36 ;(2 screens of 6x3) mul r16,r16 add YL,r0 adc YH,r1 clr posy ldi r18,3 ;counter text_input_draw_screen_loop: ldi r16,3 mov posx,r16 ;first row of letter start 3 in from edge ldi r17,5 ;counter text_input_draw_screen_loop1: lpm r16,Z+ call lcd_chr ;print character ldi r16,20 ;add columb width - 6 add posx,r16 dec r17 brne text_input_draw_screen_loop1 inc posy lpm r16,Z+ ;just to inc Z to get passed added zero byte ldi r16,15 ;NOW draw alternat letters mov posx,r16 ;first row of letter start 3 in from edge ldi r17,5 ;counter text_input_draw_screen1_loop: lpm r16,Z+ call lcd_chr ;print character ldi r16,20 ;add columb width - 6 add posx,r16 dec r17 brne text_input_draw_screen1_loop inc posy lpm r16,Z+ ;just to inc Z to get passed added zero byte dec r18 brne text_input_draw_screen_loop ;---NOW DRAW GRID---- clr posx ;DO horizontal lines.. ldi r16,15 mov posy,r16 ldi r17,3 ;counter text_input_draw_screen_gridH: clr posx ldi r16,1 text_input_draw_screen_gridH1: call lcd_pixel inc posx sbrs posx,7 ;do 128 times rjmp text_input_draw_screen_gridH1 ldi r18,16 add posy,r18 dec r17 brne text_input_draw_screen_gridH ;--- ;Do Vertical lines clr posy ldi r16,25 mov posx,r16 ldi r17,4 ;counter text_input_draw_screen_gridV: clr posy ldi r16,1 text_input_draw_screen_gridV1: call lcd_pixel inc posy sbrs posy,6 ;do 64 times rjmp text_input_draw_screen_gridV1 ldi r18,26 add posx,r18 dec r17 brne text_input_draw_screen_gridV pop r19 pop r18 pop r17 pop r16 pop ZL pop ZH ret ;----------------------------------------------------------------------- ;draw_3d_shape!! ;purpose: draw a 3d wireframe as define in mem onto screen ;Takes: r8:r9 = x, r10:r11 = y, r12:r13 = z as offset, and Z should be point to start of shape in prog mem ;Give: draws shape draw_3d_shape: push r0 push r1 push r2 push r3 push r4 push r5 push r6 push r7 push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 push r16 push r17 push r18 push r24 push r25 push r28 push r29 push ZL push ZH mov r28,ZL ;save base Z mov r29,ZH draw_3d_shape_start: lpm r16,Z+ mov r17,r16 andi r17,0b11000000 ;get top bits to find what object this is cpi r17,0b00000000 ;object is POINT breq draw_3d_shape_point cpi r17,0b01000000 ;object is POINT + LINE from PREV POINT breq draw_3d_shape_point_line cpi r17,0b10000000 ;object is LINE connecting 2 POINTS breq draw_3d_shape_line rjmp draw_3d_shape_exit ;cpi r17,0b11000000 ;end of file ;breq draw_3d_shape_exit draw_3d_shape_point: call draw_3d_shape_retive_point ;get points from mem call draw_3d_shape_add_offset ;add offset call conv_3d ;convert into x,y screen points movw r24,posx ;copy new point to last point rjmp draw_3d_shape_start draw_3d_shape_point_line: call draw_3d_shape_retive_point ;get points from mem call draw_3d_shape_add_offset ;add offset call conv_3d ;convert into x,y screen points ldi r16,1 call lcd_line ;draw line! movw r24,posx ;copy new point to last point rjmp draw_3d_shape_start ;..DRAW A LINE BETWEEN TWO POINTS draw_3d_shape_line: andi r16,0b00111111 ldi r17,6 ;number of bytes in a point def lpm r18,Z+ push ZL push ZH mov ZL,r28 ;get back base shape start mov ZH,r29 mul r17,r16 add ZL,r0 adc ZH,r1 lpm r16,Z+ call draw_3d_shape_retive_point call draw_3d_shape_add_offset ;add offset call conv_3d ;convert into x,y screen points movw r24,posx ;move first point to r24:r25 mov ZL,r28 ;get back base shape start mov ZH,r29 mul r17,r18 ;find next point add ZL,r0 adc ZH,r1 lpm r16,Z+ call draw_3d_shape_retive_point call draw_3d_shape_add_offset ;add offset call conv_3d ;convert into x,y screen points ldi r16,1 call lcd_line ;draw new line pop ZH ;gext back to current pos pop ZL rjmp draw_3d_shape_start draw_3d_shape_retive_point: andi r16,0b00111111 ;get high byte of Z mov pzh,r16 lpm pzl,Z+ ;get low byte lpm r16,Z+ andi r16,0b01111111 ;get x high byte mov pxh,r16 lpm pxl,Z+ ;get x low byte lpm r16,Z+ andi r16,0b011111111 ;get y high byte mov pyh,r16 lpm pyl,Z+ ;get y low byte ret draw_3d_shape_add_offset: add pxl,r8 adc pxh,r9 add pyl,r10 adc pyh,r11 add pzl,r12 adc pzh,r13 ret draw_3d_shape_exit: pop ZH pop ZL pop r29 pop r28 pop r25 pop r24 pop r18 pop r17 pop r16 pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop r7 pop r6 pop r5 pop r4 pop r3 pop r2 pop r1 pop r0 ret ;----------------------------------------------------------------------- ;conv_3d ;purpose: converts 3d x,y,z into possible screen postions ;Takes: r2:r3 = x, r4:r5 = y, r6:r7 = z ;Give: puts acctuall screen cordins in posx, posy, if output of bound then posy = 128 .def pxl = r2 .def pxh = r3 .def pyl = r4 .def pyh = r5 .def pzl = r6 .def pzh = r7 conv_3d: push r16 push r17 push r18 push r19 push r20 push r21 push r22 ;--DO X clr r22 ;null adder ldi r21,64 ;add 64 to Z to correct for offset add pzl,r21 adc pzh,r22 ldi r18,0x00 ldi r19,0x40 sub r18,pzl ;16384 - Z sbc r19,pzh movw r16,pxl ;move x to r16:r17 sub r16,r18 ;now subtract new z from x sbc r17,r19 brlo conv_3d_x_low ;compare z and x, if x(r24,r25) ;Give: line on LCD .def dx = r22 .def dy = r17 .def stepx = r18 .def stepy = r19 .def frac = r20 .def x2 = r24 .def y2 = r25 lcd_line: push posx push posy push r16 push r17 push r18 push r19 push r20 push r21 push r22 mov dx,x2 mov dy,y2 sub dx,posx ;find dx sub dy,posy ;finb dy sbrc dx,7 ;if dx is < 0 then make step x = -1 ldi stepx,-1 sbrs dx,7 ldi stepx,1 ;else stepx = 1 sbrc dx,7 ;if dx is < 0 then make positve neg dx ;-- sbrc dy,7 ;if dy is < 0 then make step x = -1 ldi stepy,-1 sbrs dy,7 ldi stepy,1 ;else stepy = 1 sbrc dy,7 ;if dy is < 0 then make positve neg dy call lcd_pixel ;first pixel cp dy,dx brge lcd_line_y_step ;brance if dy >= dx ;else contine.. lcd_line_x_step: mov frac,dy mov r21,dx ;lsr r21 sub frac,r21 lcd_line_x_step_loop: cp posx,x2 breq lcd_line_exit sbrs frac,7 ;check if <= 0, is so dont skip add posy,stepy sbrs frac,7 ;check if <= 0, is so dont skip sub frac,dx add posx,stepx add frac,dy call lcd_pixel rjmp lcd_line_x_step_loop lcd_line_exit: pop r22 pop r21 pop r20 pop r19 pop r18 pop r17 pop r16 pop posy pop posx ret lcd_line_y_step: mov frac,dx mov r21,dy ;lsr r21 sub frac,r21 lcd_line_y_step_loop: cp posy,y2 breq lcd_line_exit sbrs frac,7 ;check if <= 0, is so dont skip add posx,stepx sbrs frac,7 ;check if <= 0, is so dont skip sub frac,dy add posy,stepy add frac,dx call lcd_pixel rjmp lcd_line_y_step_loop ;----------------------------------------------------------------------- ;lcd_chr ;purpose: print chr in r16 at posx, posy (0 .DB 0x02, 0x01, 0x51, 0x09, 0x06 ;? .DB 0x32, 0x49, 0x59, 0x51, 0x3E ;@ .DB 0x7E, 0x11, 0x11, 0x11, 0x7E ;A .DB 0x7F, 0x49, 0x49, 0x49, 0x36 ;B .DB 0x3E, 0x41, 0x41, 0x41, 0x22 ;C .DB 0x7F, 0x41, 0x41, 0x22, 0x1C ;D .DB 0x7F, 0x49, 0x49, 0x49, 0x41 ;E .DB 0x7F, 0x09, 0x09, 0x09, 0x01 ;F .DB 0x3E, 0x41, 0x49, 0x49, 0x7A ;G .DB 0x7F, 0x08, 0x08, 0x08, 0x7F ;H .DB 0x00, 0x41, 0x7F, 0x41, 0x00 ;I .DB 0x20, 0x40, 0x41, 0x3F, 0x01 ;J .DB 0x7F, 0x08, 0x14, 0x22, 0x41 ;K .DB 0x7F, 0x40, 0x40, 0x40, 0x40 ;L .DB 0x7F, 0x02, 0x0C, 0x02, 0x7F ;M .DB 0x7F, 0x04, 0x08, 0x10, 0x7F ;N .DB 0x3E, 0x41, 0x41, 0x41, 0x3E ;O .DB 0x7F, 0x09, 0x09, 0x09, 0x06 ;P .DB 0x3E, 0x41, 0x51, 0x21, 0x5E ;Q .DB 0x7F, 0x09, 0x19, 0x29, 0x46 ;R .DB 0x46, 0x49, 0x49, 0x49, 0x31 ;S .DB 0x01, 0x01, 0x7F, 0x01, 0x01 ;T .DB 0x3F, 0x40, 0x40, 0x40, 0x3F ;U .DB 0x1F, 0x20, 0x40, 0x20, 0x1F ;V .DB 0x3F, 0x40, 0x38, 0x40, 0x3F ;W .DB 0x63, 0x14, 0x08, 0x14, 0x63 ;X .DB 0x07, 0x08, 0x70, 0x08, 0x07 ;Y .DB 0x61, 0x51, 0x49, 0x45, 0x43 ;Z .DB 0x00, 0x7F, 0x41, 0x41, 0x00 ;[ .DB 0x55, 0x2A, 0x55, 0x2A, 0x55 ;55 .DB 0x00, 0x41, 0x41, 0x7F, 0x00 ;] .DB 0x04, 0x02, 0x01, 0x02, 0x04 ;^ .DB 0x40, 0x40, 0x40, 0x40, 0x40 ;_ .DB 0x00, 0x01, 0x02, 0x04, 0x00 ;' .DB 0x20, 0x54, 0x54, 0x54, 0x78 ;a .DB 0x7F, 0x48, 0x44, 0x44, 0x38 ;b .DB 0x38, 0x44, 0x44, 0x44, 0x20 ;c .DB 0x38, 0x44, 0x44, 0x48, 0x7F ;d .DB 0x38, 0x54, 0x54, 0x54, 0x18 ;e .DB 0x08, 0x7E, 0x09, 0x01, 0x02 ;f .DB 0x0C, 0x52, 0x52, 0x52, 0x3E ;g .DB 0x7F, 0x08, 0x04, 0x04, 0x78 ;h .DB 0x00, 0x44, 0x7D, 0x40, 0x00 ;i .DB 0x20, 0x40, 0x44, 0x3D, 0x00 ;j .DB 0x7F, 0x10, 0x28, 0x44, 0x00 ;k .DB 0x00, 0x41, 0x7F, 0x40, 0x00 ;l .DB 0x7C, 0x04, 0x18, 0x04, 0x78 ;m .DB 0x7C, 0x08, 0x04, 0x04, 0x78 ;n .DB 0x38, 0x44, 0x44, 0x44, 0x38 ;o .DB 0x7C, 0x14, 0x14, 0x14, 0x08 ;p .DB 0x08, 0x14, 0x14, 0x18, 0x7C ;q .DB 0x7C, 0x08, 0x04, 0x04, 0x08 ;r .DB 0x48, 0x54, 0x54, 0x54, 0x20 ;s .DB 0x04, 0x3F, 0x44, 0x40, 0x20 ;t .DB 0x3C, 0x40, 0x40, 0x20, 0x7C ;u .DB 0x1C, 0x20, 0x40, 0x20, 0x1C ;v .DB 0x3C, 0x40, 0x30, 0x40, 0x3C ;w .DB 0x44, 0x28, 0x10, 0x28, 0x44 ;x .DB 0x0C, 0x50, 0x50, 0x50, 0x3C ;y .DB 0x44, 0x64, 0x54, 0x4C, 0x44 ;z