;Memory LCD Maze for Intel 8048 ;Designed to be assembled with ASM48 0.4.1 ;Warning: This program uses horrible programming practices to fit the program in the smallest space I could .equ LCD_WIDTH 400 .equ LCD_HEIGHT 240 .org 0x0000 begin: clr A outl P1,A call clearLCD mov R4,LCD_HEIGHT ;loop through all rows of the LCD drawLoop: mov A,R4 call drawMazeRow djnz R4,drawLoop jmp .here ;end of program (loop here forever) ;spiLCD - writes the byte stored in A to the Sharp Memory LCD ;uses R6 and R7 ; ;This function will set CS high, but will not set it low (so that multiple bytes can be written in a row) ; ;LCD Pinout: ; P1-0 - Data Out (MOSI) ; P1-1 - CLK ; P1-2 - CS (active high because Sharp likes to be different) ; ;uses R6 and R7 ;Note: A contains 0x00 when this function is done. spiLCD: mov R6,#8 ;repeat 8 times spiLCDLoop: rrc A ;store LSB in carry flag and shift right mov R7,A ;save copy of A mov A,#0x02 ;select LCD (will be shifted to 0x04) rlc A ;move carry flag (current data bit) to MOSI outl P1,A orl P1,#0x02 ;high clock edge mov A,R7 ;restore A djnz R6,spiLCDLoop retr ;clearLCD - clears the LCD; (0x02, 0x00) ;uses R2 and R3 clearLCD: mov A,#0x40 ;0x02 backwards call spiLCD call spiLCD ;0x00 outl P1,A ;deselect LCD retr ;getSquareDirection - find out what walls need to be drawn and store in A ;display column should be in R2 ;display row should be in R3 ;1 = don't draw bottom walls ;0 = don't draw side wall ;uses R6 and R7 getSquareDirection: mov A,R3 ;get row and store in R7 anl A,#0xf0 jz firstRow ;skip calculation if it part of the first row in the grid swap A mov R7,A mov A,R2 ;get column dec A clr C rrc A ;no need to check if it is the first column because the algorithm makes the first column in correct direction anyways. add A,R7 ;generate random-ish looking number based on row an column rr A ;the formula is: rr(row + column) ^ row xrl A,R7 ;(where rr is the rotate right instruction) mov r7,#0 ;turn generated numbers into booleans (1 or 0) based on parity mov R6,#8 squareDirectionLoop: rrc A jnc skipInc xch A,R7 inc A xch A,R7 skipInc: djnz R6,squareDirectionLoop mov A,R7 anl A,#0x01 retr firstRow: ;A should already be storing 0 here. inc A retr ;drawMazeRow - draw a line of the Maze to line A on the LCD ;uses R2 and R3 drawMazeRow: mov R3,A mov A,#0x01 ;0x80 backwards call spiLCD mov A,R3 ;line# dec A ;offset line# because LCD starts counting at 1 instead of 0. xch A,R3 call spiLCD mov R2,#LCD_WIDTH/8 drawMazeRowLoop: mov A,R3 ;get row anl A,#0x0e ;check if row is one of the bottom two rows of a square jnz checkIfOdd call getSquareDirection rrc A clr A ;if it is a bottom row of a square, the segment should be filled unless there is a path through it. jc continueMazeRow checkIfOdd: mov A,R2 ; get column rrc A ;check if current segment is an odd half of a column jc odd mov A,#0xff ;if it is even, the segment should be blank. jmp continueMazeRow odd: call getSquareDirection rrc A mov A,#0xff jc continueMazeRow mov A,#0x3f continueMazeRow: call spiLCD djnz R2,drawMazeRowLoop call spiLCD ;0x00 call spiLCD ;0x00 outl P1,A ;deselect LCD retr