{{ P2_Maze_Generator version 1.4 for FPGA V18 Ozpropdev 11th April 2017 VGA 800 * 600 }} single_cog = false 'set true for Nano/BeMucro-A2 single cog FPGA builds maze_size = 100 '296 max (Must be even number) width = 3 build_speed = (80_000_000 * 10) / (maze_size*maze_size) '10 second build _mazegen_cog = 2 _mazeplot_cog = 1 block_size = (592 / maze_size) centre_x = 400 - ((maze_size * block_size)/2) centre_y = 300 - ((maze_size * block_size)/2) sys_clk = 80_000_000 baudrate = 1_000_000 '115_200 rx_pin = 63 tx_pin = 62 nco = (sys_clk / baudrate) * $1_0000 & $FFFFFC00 nco_f = (sys_clk - ((sys_clk / baudrate) * baudrate)) * 64 / baudrate intensity = 80 '0..128 fclk = 80_000_000.0 fpix = 50_000_000.0 fset = (fpix / fclk * 2.0) * float($4000_0000) vsync = 0 'vsync pin (all FPGA boards now) '************************************************************************************************ DAT org mov x,##single_cog cmp x,##-1 wz if_e coginit #0,##@mazegen coginit #_mazegen_cog,##@mazegen wrlut ##$1f00,#0 'dark blue background wrlut ##$00ff0000,#1 'green foreground setxfrq ##round(fset) 'set transfer frequency to 25MHz setcy ##intensity << 24 'r set colorspace for rgb setci ##intensity << 16 'g setcq ##intensity << 08 'b setcmod #%01_0_000_0 'enable colorspace conversion wrpin dacmode,#0 'enable dac modes in pins 0..3 wrpin dacmode,#1 wrpin dacmode,#2 wrpin dacmode,#3 '************************************************************************************************ '************************************************************************************************ field loc ptra,#@buffer_select rdlong x,ptra wz rdlong y,ptra[1] jnatn #same_frame 'new frame available? wrlong y,ptra[0] 'switch to new frame cogatn ## |< _mazeplot_cog 'signal frame switched ok testb y,#0 wz same_frame if_z rdfast #0,##video_buffer 'set frame start address if_nz rdfast #0,##video_buffer2 mov x,#36+4 'top blanks call #blank mov x,##600 'set visible lines line call #hsync 'do horizontal sync xcont m_rf,#0 'visible line djnz x,#line 'another line? mov x,#23-4 'bottom blanks call #blank drvn #vsync 'sync on mov x,#2 'sync blanks call #blank drvn #vsync 'sync off jmp #field 'loop blank call #hsync 'blank lines xcont m_vi,#0 _ret_ djnz x,#blank hsync xcont m_bs,#0 'horizontal sync xcont m_sn,#1 _ret_ xcont m_bv,#0 dacmode long %0000_0000_000_1010000000000_01_00000_0 m_bs long $CF000000+56 'before sync m_sn long $CF000000+120 'sync m_bv long $CF000000+64 'before visible m_vi long $CF000000+800 'visible m_rf long $4F000000+800 'visible rlong 8bpp lut x res 1 y res 1 '************************************************************************************************ '************************************************************************************************ { How it works: Each cell of the maze is represented by a 4 bit(nibble). Each bit of the nibble represents a wall of the cell. Bit 0 for above,Bit 1 = right,Bit 2 = below and Bit 3 = left. A random starting position is set as the current cell. The main loop scans in all 4 directions from the current cell to determine valid moves (complete cells = $f). A direction is randomly chosen and the move is done by "breaking" through the current cell wall and the opposite wall of the new "current cell". If all cells are broken the maze is now complete. This main loop is repeated until no more valid moves are available on the current path (dead end). When a dead end is reached a new starting position is selectd randomly on a previous built "path" that has available moves (unbroken cells adjacent). The main loop is restarted again. } orgh $400 org mazegen jmp #hub_code cell long 0 cellx long 0 celly long 0 ax long 0 bx long 0 cx long 0 dx long 0 xx long 0 yy long 0 current_x long 0 current_y long 0 dir long 0 valid_dir long 0 rnd long 0 char long 0 status long 0 qx long 0 kx long 0 jx long 0 sx long 0 yx long 0 nano_mode long single_cog new_dir long 0 total long 0 valid_moves long 0 _ffffffff long -1 bc_table long $32212110 long $43323221 adj_x long 0 adj_y long 0 dir_mask long 0 '************************************************************************************************ orgh hub_code call #setup setword dirb,##$ffff,#0 loc pb,#@cells cmp nano_mode,##-1 wz if_ne coginit #_mazeplot_cog,##@maze_view restart call #init_cells waitx ##80_000_000 * 2 call #get_random_xy 'random starting cell mov current_x,xx mov current_y,yy mov total,##maze_size*maze_size sub total,#1 'main loop <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< new_direction call #get_valid_moves tjz valid_moves,#dead_end getrnd rnd 'pick a random direction from mov dir,rnd 'the valid moves and dir,#3 decod new_dir,dir andn outb,#$f or outb,new_dir and new_dir,valid_moves wz if_z jmp #new_direction 'try again call #break_wall sub total,#1 wz 'maze complete? if_nz waitx ##build_speed if_nz jmp #new_direction setword outb,#0,#0 'maze done. cmp nano_mode,#0 wz call #send_maze waitx ##80_000_000 * 5 'pause 5 seconds jmp #restart 'find a new starting point on existing paths that has valid space to move. dead_end call #get_random_xy mov cellx,xx mov celly,yy call #get_cell cmp cell,#$f wz if_e jmp #dead_end mov current_x,xx mov current_y,yy call #get_valid_moves cmp valid_moves,#0 wz if_z jmp #dead_end jmp #new_direction '************************************************************************************************ get_random_xy getrnd rnd mov ax,rnd mov xx,ax and xx,##$3ff newx cmp xx,##maze_size-1 wz,wc if_a jmp #get_random_xy newy getrnd rnd mov ax,rnd mov yy,ax and yy,#$1ff cmp yy,#maze_size-1 wz,wc if_a jmp #newy ret '************************************************************************************************ get_cell mul celly,#maze_size/2 shr cellx,#1 wc add cellx,pb add cellx,celly rdbyte cx,cellx if_nc getnib cell,cx,#1 if_c getnib cell,cx,#0 ret '************************************************************************************************ set_cell mul celly,#maze_size/2 shr cellx,#1 wc add cellx,pb add cellx,celly rdbyte cx,cellx if_nc setnib cx,cell,#1 if_c setnib cx,cell,#0 wrbyte cx,cellx ret '************************************************************************************************ init_cells loc ptra,#@hold tjnz nano_mode,#ic2 wrlong #1,ptra waitatn 'sync with video driver ic2 loc ptra,#@cells rep @.loop,##(((maze_size/2)*maze_size)/4+1) wrlong _ffffffff,ptra++ .loop loc ptra,#@hold wrlong #0,ptra ret '************************************************************************************************ get_valid_moves cmp current_y,#0 wz if_z bitl valid_moves,#0 if_z jmp #vm2 mov celly,current_y sub celly,#1 mov cellx,current_x call #get_cell cmp cell,#$f wz bitz valid_moves,#0 vm2 cmp current_x,##maze_size-1 wz if_e bitl valid_moves,#1 if_e jmp #vm3 mov cellx,current_x add cellx,#1 mov celly,current_y call #get_cell cmp cell,#$f wz bitz valid_moves,#1 vm3 cmp current_y,#maze_size-1 wz if_e bitl valid_moves,#2 if_e jmp #vm4 mov celly,current_y add celly,#1 mov cellx,current_x call #get_cell cmp cell,#$f wz bitz valid_moves,#2 vm4 cmp current_x,#0 wz if_e bitl valid_moves,#3 if_e ret mov cellx,current_x sub cellx,#1 mov celly,current_y call #get_cell cmp cell,#$f wz bitz valid_moves,#3 ret '************************************************************************************************ '0 above '1 right '2 below '3 left break_wall decod dir_mask,dir mov cellx,current_x mov celly,current_y call #get_cell jmprel dir jmp #_above jmp #_right jmp #_below jmp #_left _above mov adj_x,#0 mov adj_y,##-1 jmp #bw2 _right mov adj_x,#1 mov adj_y,#0 jmp #bw2 _below mov adj_x,#0 mov adj_y,#1 jmp #bw2 _left mov adj_x,##-1 mov adj_y,#0 bw2 andn cell,dir_mask mov cellx,current_x mov celly,current_y call #set_cell add current_x,adj_x add current_y,adj_y mov cellx,current_x mov celly,current_y call #get_cell shr dir_mask,#1 wc bitc dir_mask,#3 shr dir_mask,#1 wc bitc dir_mask,#3 andn cell,dir_mask mov cellx,current_x mov celly,current_y call #set_cell ret '************************************************************************************************ bit_count xor cell,#$f altgn cell,#bc_table getnib cell,0-0,#0 ret '************************************************************************************************ '************************************************************************************************ { This cog builds the video frames for the video driver. When a "new" frame is ready the video driver is signalled using COGATN. The cog then waits for the video driver to "acknowledge" the switch to the new frame. This cog then start on the "next" frame. } org maze_view call #clear_screen plot_maze loc ptra,#@hold .loop rdlong q,ptra wz if_z jmp #plot_go cogatn # |< _mazegen_cog hold_loop rdlong q,ptra wz if_nz jmp #hold_loop plot_go bitn buff_sel,#0 'switch buffers testb buff_sel,#0 wc if_nc loc ptra,#@video_buffer if_c loc ptra,#@video_buffer2 loc pb,#@cells mov pa,ptra clear_buffer rep @.loop,##(800/32)*600 wrlong #0,ptra++ .loop mov xcell2,#0 mov ycell2,#0 plot_loop mov cellx2,xcell2 mov celly2,ycell2 call #get_cell2 mov xp,xcell2 mul xp,#block_size mov yp,ycell2 mul yp,#block_size plot_above mov xp2,xp mov yp2,yp mov size,#block_size .loop testb cell2,#0 wc if_nc jmp #plot_right mov xx2,xp2 mov yy2,yp2 call #set_pixel add xp2,#1 djnz size,#.loop plot_right cmp xcell2,#maze_size-1 wz if_ne jmp #plot_below mov xp2,xp add xp2,##block_size-1 mov yp2,yp mov size,#block_size .loop testb cell2,#1 wc if_nc jmp #plot_below mov xx2,xp2 mov yy2,yp2 call #set_pixel add yp2,#1 djnz size,#.loop plot_below cmp ycell2,#maze_size-1 wz if_ne jmp #plot_left mov xp2,xp mov yp2,yp add yp2,##block_size-1 mov size,#block_size .loop testb cell2,#2 wc if_nc jmp #plot_left mov xx2,xp2 mov yy2,yp2 call #set_pixel add xp2,#1 djnz size,#.loop plot_left mov xp2,xp mov yp2,yp add yp2,#1 mov size,#block_size-1 .loop testb cell2,#3 wc if_nc jmp #plot_next mov xx2,xp2 mov yy2,yp2 call #set_pixel add yp2,#1 djnz size,#.loop plot_next incmod xcell2,##maze_size-1 wz if_z incmod ycell2,#maze_size-1 wz if_nz jmp #plot_loop loc ptra,#@change_buffer wrlong buff_sel,ptra cogatn # |< 0 'signal new frame available waitatn 'frame switched ok jmp #plot_maze q long 0 size long 0 xp long 0 yp long 0 xp2 long 0 yp2 long 0 xcell2 long 0 ycell2 long 0 clear_screen loc ptra,#@video_buffer rep @.loop,##(800/32)*600 wrlong #0,ptra++ .loop clear_screen2 loc ptra,#@video_buffer2 rep @.loop,##(800/32)*600 wrlong #0,ptra++ .loop ret set_pixel add xx2,#centre_x decod ax2,xx2 mov bx2,xx2 shr bx2,#5 shl bx2,#2 add bx2,pa mov cx2,yy2 add cx2,#centre_y mul cx2,#100 add cx2,bx2 rdlong dx2,cx2 or dx2,ax2 wrlong dx2,cx2 ret get_cell2 mul celly2,#maze_size/2 shr cellx2,#1 wc add cellx2,pb add cellx2,celly2 rdbyte cx2,cellx2 if_nc getnib cell2,cx2,#1 if_c getnib cell2,cx2,#0 ret cell2 long 0 cellx2 long 0 celly2 long 0 ax2 long 0 bx2 long 0 cx2 long 0 dx2 long 0 xx2 long 0 yy2 long 0 buff_sel long 0 '************************************************************************************************ 'output maze in text format orgh send_maze mov char,#16 call #send_char loc ptra,#@cells mov sx,#maze_size vert mov qx,#maze_size / 2 horiz mov char,#"+" call #send_char rdbyte kx,ptra++ getnib jx,kx,#1 testb jx,#0 wc if_c mov char,#"-" if_nc mov char,#" " mov yx,#width .loop call #send_char djnz yx,#.loop hz2 mov char,#"+" call #send_char getnib jx,kx,#0 testb jx,#0 wc if_c mov char,#"-" if_nc mov char,#" " mov yx,#width .loop call #send_char djnz yx,#.loop djnz qx,#@horiz mov char,#"+" call #send_char call #newline sub ptra,#maze_size/2 mov qx,#maze_size/2 horiz2 rdbyte kx,ptra++ getnib jx,kx,#1 testb jx,#3 wc if_c mov char,#"I" if_nc mov char,#" " call #send_char mov char,#" " mov yx,#width .loop call #send_char djnz yx,#.loop h3 getnib jx,kx,#0 testb jx,#3 wc if_c mov char,#"I" if_nc mov char,#" " call #send_char mov char,#" " mov yx,#width .loop call #send_char djnz yx,#.loop djnz qx,#horiz2 mov char,#"|" call #send_char call #newline djnz sx,#vert bottom_edge mov sx,#maze_size .loop mov char,#"+" call #send_char mov char,#"-" mov yx,#width .loop2 call #send_char djnz yx,#.loop2 djnz sx,#.loop mov char,#"+" call #send_char call #newline ret newline mov char,#13 send_char rdpin status,#tx_pin wc if_c jmp #send_char wypin char,#tx_pin ret wc setup wrpin #%11111_0,#rx_pin wxpin ##nco | nco_f << 10 | 7,#rx_pin dirh #rx_pin wrpin #%1_11110_0,#tx_pin wxpin ##nco | nco_f << 10 |7,#tx_pin _ret_ dirh #tx_pin '************************************************************************************************ orgh hold long 0 buffer_select long 0 change_buffer long 0 cells byte $ff[(maze_size/2)*maze_size] byte 0[32] 'padding video_buffer long 0[(800/32)*600] video_buffer2 long 0[(800/32)*600]