'PROJECT PBP TO PROTON
Device 16F877A
'SUSCRIBETE A MI CANAL EN YOUTUBE --->https://www.youtube.com/KORZ ES
'ORIGINAL TOPIC ---> http://www.picbasic.co.uk/forum/showthread.php?t=18416&page=2&highlight=matrix+serial
'VIDEO ----> https://www.youtube.com/watch?v=HugwQ4b9iBU
'DIGITAL RESITOR http://www.protonbasic.co.uk/archive/index.php/t-53777.htm
Xtal 20
'Declare NO_Clrwdt ' watchdog is cleared manually PBP a Proton+ conversion
'more info --->http://www.protonbasic.co.uk/group.php?gmid=35&do=discuss#gmessage35
Declare Watchdog = 1
Declare All_Digital = True
Declare LCD_Type 0 ' LCD alfanumerica
Declare LCD_Interface 4 ' 4 lineas de datos
Declare LCD_DTPin PORTA.0 ' lineas de datos al PORTB RB4->RB7
Declare LCD_ENPin PORTB.3 ' EN al pin RB2
Declare LCD_RSPin PORTA.4 ' RS al pin RB3
Declare LCD_Lines 2 ' LCD de cuatro lineas
Declare LCD_DataUs 50 ' LCD timing
Declare LCD_CommandUs 2000 '
'
DATA 142,145,145,143,129,130,140,128 '9 digit roll stored horizontal
DATA 142,145,147,149,153,145,142,128 '0
DATA 132,140,132,132,132,132,142,128 '1
DATA 142,145,129,130,132,136,159,128 '2
DATA 159,130,132,130,129,145,142,128 '3
DATA 130,134,138,146,159,130,130,128 '4
DATA 159,144,158,129,129,145,142,128 '5
DATA 134,136,144,158,145,145,142,128 '6
DATA 159,129,130,132,136,136,136,128 '7
DATA 142,145,145,142,145,145,142,128 '8
DATA 142,145,145,143,129,130,140,128 '9
DATA 142,145,147,149,153,145,142,128 '0
'
DATA %01110000 ' invader frame a
DATA %00011000 ' stored vertical
DATA %01111101 '
DATA %10110110 '
DATA %10111100 '
DATA %00111100 '
DATA %10111100 '
DATA %10110110 '
DATA %01111101 '
DATA %00011000 '
DATA %01110000 '
DATA %10011100 ' invader frame b
DATA %10011000 ' stored vertical
DATA %01111101 '
DATA %00110110 '
DATA %00111100 '
DATA %00111100 '
DATA %00111100 '
DATA %00110110 '
DATA %01111101 '
DATA %10011000 '
DATA %10011100 '
'
DATA " edit 2015" ' original LC2D V2 - (c) Brek Martin
'
Dim dis[51] As Byte ' monochrome display buffer 24x17
Dim rolls[8] As Byte
'How does one alias an element in a byte array?
Dim rolls0 As rolls#0 : Dim rolls1 As rolls#1
Dim rolls2 As rolls#2 : Dim rolls3 As rolls#3 '
Dim rolls4 As rolls#4 : Dim rolls5 As rolls#5 '
Dim rolls6 As rolls#6 : Dim rolls7 As rolls#7
Dim L0 As Byte ' LCD RAM index and used as counter
Dim CW As Byte : Dim CL As Byte ' multi purpose counters
Dim lind As Byte : Dim pind As Byte ' framebuffer indexing variables
Dim slug As Byte :Dim invert As Byte ' set invert 0xFF to invert display
Dim wtemp As Word '
Dim temp As wtemp.Byte0 '
Dim tempb As wtemp.Byte1 '
Dim px As Byte : Dim py As Byte ' coordinates for library routines
'''''''''''''''''''''''''''''''''''''''''''''''''''''
' END OF DISPLAY BUFFER CODESPACE '
'''''''''''''''''''''''''''''''''''''''''''''''''''''
'
Dim x As Byte ' user coordinates for 2D graphics
Dim y As Byte ' these are for the user program
'
Dim dy As Byte ' line drawing variables can
Dim y1 As Byte ' be removed if not using lines
Dim y0 As Byte ' line drawing may break if start
Dim dx As Byte ' and end points are the same
Dim x1 As Byte ' which is not yet tested
Dim x0 As Byte ' thanks to oogabooga to for
Dim stepx As Byte ' optimisation of my code for
Dim stepy As Byte ' PBP unsigned integer bytes
Dim frac As Byte ' expand to words for bigger LCD
'
Dim ftick As Byte ' frame count variables can
Dim frame As Byte ' be removed if not counting
'
Dim dval As Byte ' value for printed variable
Dim digit As Byte ' buffer for printing sprites
Dim index As Byte ' eeprom index for sprite data
Dim dgx As Byte ' coordinates to print sprite
Dim dgy As Byte '
Dim demd As Byte ' actual digits on the screen
Dim demdl As Byte '
Dim dfc As Byte ' digit frame counter
'
' circle drawing variables can be removed
' if you remove the circle drawing routine
' some variables are shared with square drawing
' this circle routine is borrowed from the GLCD
' library posted by Dave on MELabs PBP forum
' do not draw circles with radius less than 3.
'
Dim cx As Byte ' shared with square drawing routine
Dim cy As Byte '
Dim glc_x As Byte '
Dim glc_y As Byte '
Dim glc_s As Word ' slope
Dim radius As Byte ' radius
'
Dim cdx As Byte ' circle demo horizontal coordinate
'
Dim doff As Byte ' digit odometer effect variables
Dim doffl As Byte '
Dim doffm As Byte '
Dim dcompl As Byte '
Dim dcompm As Byte '
Dim ddirl As Bit ' digit counting direction variables
Dim ddirm As Bit ' not implemented yet - out of memory
'
Dim xdir As Bit ' direction variables that can be
Dim ydir As Bit ' removed if not running the demo
'
Dim backled As Bit ' LED backlight flash status
'
invert = $FF ' 0xFF to invert display colours
'
'
' execution time!
'
CMCON = 7 ' set portb to digital
TRISB.6 = 0 'set LCD backlight output
'
'the demo program turns on the backlight
'turn it on here if your program does not
'portb.6 = 1'turn on LCD backlight
'
backled = 1 ' initially set led backlight on
ftick = 0 ' reset demo section counter
frame = 0 ' reset frame counters
x = 2 ' set intial point coordinates
y = 2 '
cdx = 11 ' set initial circle position
dfc = 0 ' reset some variables that could
doff = 0 ' break things if not initialised
dval = 0 '
demd = 0 '
demdl = 0 '
digit = 0 '
'
DelayMS 1200 'delayms for LCD to start
Print $FE,1 'clear LCD
'
'
cycle: ' main routine - demo user program
@ clrwdt ; clear watchdog timer manually
'
x = x - 1 ' move the point for the demo
If xdir = 0 Then ' the moving point controlls
x = x + 2 ' most of the demo parts
EndIf
y = y - 1
If ydir = 0 Then
y = y + 2
EndIf
'
If ftick < 4 & ftick != 1 Then ' draw the moving point
px = x+0 : py = y+0 ' draw point
GoSub setpixel
EndIf
'
If ftick = 0 Then ' draw rest of the ball around moving point
px = x+1 : py = y+0 ' this is the first demo part
GoSub setpixel
px = x-1 : py = y+0
GoSub setpixel
px = x+0 : py = y+1
GoSub setpixel
px = x+0 : py = y-1
GoSub setpixel
EndIf
'
If x > 21 And xdir = 0 Then ' check the screen bounds
xdir = 1 ' for the point we are moving around
EndIf
If x < 1 And xdir = 1 Then
xdir = 0
EndIf
If y > 15 And ydir = 0 Then
ydir = 1
EndIf
If y < 1 And ydir = 1 Then
ydir = 0
EndIf
'
If ftick = 1 Then ' draw dynamic circles
cx = x : cy = y ' this is the second demo part
radius = (y/2) + 2
GoSub drawcircle
EndIf
'
If ftick = 2 Then ' draw dynamic lines
x0 = 0 : y0 = 0 ' which is an example of diagonal lines
x1 = x : y1 = y
GoSub drawline
x0 = x : y0 = y
x1 = 22 : y1 = 0
GoSub drawline
x0 = x : y0 = y
x1 = 22 : y1 = 16
GoSub drawline
x0 = 0 : y0 = 16
x1 = x : y1 = y
GoSub drawline
EndIf
'
If ftick = 3 Then ' draw the crosshair effect
x0 = x : y0 = 0 ' which is an example of straight lines
x1 = x : y1 = 16
GoSub drawline
x0 = 0 : y0 = y
x1 = 22 : y1 = y
GoSub drawline
EndIf
'
If ftick = 4 Then ' draw digits
dval = demd /10 ' which is an example of drawing sprites
demdl = demd ' where the data was stored horizontal
demdl = demdl - (dval * 10)
dgx = x-6 : dgy = y-4
GoSub printdigit
dval = demdl
dgx = x+1 : dgy = y-4
GoSub printdigit
EndIf
'
If ftick = 5 Then ' squares
x0 = 11 : y0 = 8
radius = dfc
GoSub drawsquare
EndIf
'
If ftick = 6 Then ' squares with strobe
radius = dfc ' coords were set in previous section
GoSub drawsquare
EndIf
'
If ftick = 7 Then ' more squares
x0 = x : y0 = y
radius = 5
GoSub drawsquare
EndIf
'
If ftick = 8 Then ' dynamic squares
x0 = x : y0 = y
radius = y/2
GoSub drawsquare
EndIf
'
If ftick = 9 Then ' draw invader sprite
dgx = x-5 : dgy = y-4 ' which is an example of animated sprite
GoSub printsprite ' where the data was stored vertically
EndIf
'
If ftick = 10 Then ' circles trick
cx = cdx : cy = 8 ' a trick to look like the entire LCD is used
radius = 7
GoSub drawcircle
cx = cdx + 24
GoSub drawcircle
cdx = cdx - 1
EndIf
'
If ftick == 11 Or ftick == 12 Then ' dynamic circles trick with strobe
cx = cdx : cy = 8 ' a trick to look like the entire LCD is used
radius = (y/2) + 2 '
If ftick = 12 Then
cy = 15 - y
EndIf
GoSub drawcircle
cx = cdx + 24
GoSub drawcircle
cdx = cdx - 1
EndIf
'
If ftick = 13 Then ' rolling odometer effect display
dval = demd /10 ' the odometer display also moves
demdl = demd ' around the display
demdl = demdl - (dval * 10)
If dval != dcompm Then
'ddirm = 0 ' determine digit count direction
'IF dval < dcompm THEN ' odometer only works on a variable
'ddirm = 1 ' that is being incremented by one
'ENDIF ' not enough memory to reverse
dcompm = dval
doffm = 8
EndIf
doff = doffm
If doffm > 0 Then
doffm = doffm - 1
EndIf
dgx = x-6 : dgy = y-4
GoSub printdigit
If demdl != dcompl Then
'ddirl = 0 ' determine digit count direction
'IF demdl < dcompl THEN ' oops, ran out of memory to reverse
'ddirl = 1 ' the roll direction of movement
'ENDIF ' so this is incomplete
dcompl = demdl
doffl = 8
EndIf
doff = doffl
If doffl > 0 Then
doffl = doffl - 1
EndIf
dval = demdl
dgx = x+1 : dgy = y-4
GoSub printdigit
EndIf
'
If ftick == 14 Then ' dynamic squares trick
x0 = cdx : y0 = 8 ' a trick to look like the entire LCD is used
radius = (y/2) + 2 '
GoSub drawsquare
x0 = cdx + 24
GoSub drawsquare
cdx = cdx - 1
EndIf
'
If cdx = 242 Then ' check bounds for moving circle demos
cdx = 10 '
EndIf '
'
If ftick = 15 Then ' reset demo section counter
ftick = 0 ' there are currently fifteen demo parts
doff = 0
EndIf
'
'
GoSub writecg ' write the frame buffer to LCD
'
'
frame = frame + 1 ' count actual frames
If frame = 150 Then '
frame = 0 '
ftick = ftick + 1 ' frame counter increments demo counter
invert = $00 ' revert to normal after first section
EndIf
'
dfc = dfc + 1 ' increment the dynamic squares width
If dfc > 8 Then '
dfc = 0 '
demd = demd + 1 ' increment counter for display variable
EndIf '
If demd > 99 Then ' keep display variable in two digit range
demd = 0 '
EndIf '
'
If ftick = 4 Or ftick = 9 Or ftick = 13 Then ' variable sprite delay
DelayMS ftick*20 ' for all digit and invader sprites
EndIf ' otherwise lcd lag messes up the display
'
PORTB.6 = 1 ' strobe the LED backlight
If ftick = 6 Or ftick = 11 Then ' for these demo sections only
backled = backled + 1 ' alternate backlight status
PORTB.6 = backled ' set led backlight to current status
EndIf '
'
GoTo cycle ' end main routine - do the next frame
'
'
'
'
setpixel: ' size and performance win for V2
lind = py * 3 ' byte index for line
pind = 0
slug = px
If px > 7 Then
pind = 1
slug = px - 8
EndIf
If px > 15 Then
pind = pind + 1
slug = px - 16
EndIf
If lind+pind < 51 Then ' range check
temp = dis[lind+pind]
For CW = 0 To 7
If slug = CW Then
temp.7 = 1
EndIf
wtemp = wtemp << 1
Next CW
dis[lind+pind] = tempb
EndIf
Return
'
writecg: ' size, ram and performance win for V2
L0 = $40 ' reset lines
For CL = 0 To 7 ' write first half of display
For CW = 0 To 3
rolls[CW] = (dis[0] ^ invert) >> 3
GoSub Rotate
Next CW
Print $FE,L0+$00,rolls[0]
Print $FE,L0+$08,rolls[1]
Print $FE,L0+$10,rolls[2]
Print $FE,L0+$18,rolls[3]
L0 = L0 + 1'
Next CL
For CW = 0 To 23 ' skip invisible line
GoSub RotateDisplay
Next CW
L0 = $60 ' reset lines
For CL = 0 To 7 ' write second half of display
For CW = 0 To 3
rolls[CW] = (dis[0] ^ invert) >> 3
GoSub Rotate
Next CW
Print $FE,L0+$00,rolls[0]
Print $FE,L0+$08,rolls[1]
Print $FE,L0+$10,rolls[2]
Print $FE,L0+$18,rolls[3]
L0 = L0 + 1'
Next CL
' draw to LCD
Print $FE,$80 'draw first line of display
For CL = 0 To 3
Print 0,1,2,3 '
Next CL
Print $FE,$C0 'draw second line of display
For CL = 0 To 3
Print 4,5,6,7 '
Next CL
Return
'
printdigit: ' print a single digit to screen
index = dval * 8' set index position for digit
For L0 = 0 To 7
GoSub readeep
For CL = 0 To 4
If digit.4 = 1 Then
px = dgx+CL : py = dgy+L0
GoSub setpixel
EndIf
digit = digit << 1
Next CL
index = index + 1
Next L0
Return
'
printsprite: ' print a monochrome graphic sprite to screen
index = 88 ' set index position for sprite
If frame.3 = 1 Then ' select frame
index = index + 11
EndIf
For L0 = 0 To 10
GoSub readeep
For CL = 0 To 7
If digit.0 = 1 Then
py = dgx+CL : px = dgy+L0
GoSub setpixel
EndIf
digit = digit >> 1
Next CL
index = index + 1
Next L0
Return
'
readeep:
'READ index+8,digit ' not ever using the rolling odometer effect
digit = ERead (index-doff)+8' are using rolling odometer effect sometimes
Return ' slight performance penalty if you are
'
drawsquare: ' draw square to screen
cx = radius : cy = 0
While cx >= cy
px = cx + x0 : py = cy + y0
GoSub setpixel
px = cy + x0 : py = cx + y0
GoSub setpixel
px = -cx + x0 : py = cy + y0
GoSub setpixel
px = -cy + x0 : py = cx + y0
GoSub setpixel
px = -cx + x0 : py = -cy + y0
GoSub setpixel
px = -cy + x0 : py = -cx + y0
GoSub setpixel
px = cx + x0 : py = -cy + y0
GoSub setpixel
px = cy + x0 : py = -cx + y0
GoSub setpixel
cy = cy + 1
Wend
Return
'
drawcircle: ' draw circle to screen
glc_x = 0
glc_y = radius
glc_s = 2-2*radius
While glc_x <= glc_y
px = glc_x+cx : py=glc_y+cy
GoSub setpixel
px = cx-glc_x : py=glc_y+cy
GoSub setpixel
px = cx+glc_x : py=cy-glc_y
GoSub setpixel
px = cx-glc_x : py=cy-glc_y
GoSub setpixel
px = glc_y+cx : py=glc_x+cy
GoSub setpixel
px = cx-glc_y : py=cy+glc_x
GoSub setpixel
px = cx+glc_y : py=cy-glc_x
GoSub setpixel
px = cx-glc_y : py=cy-glc_x
GoSub setpixel
If glc_s.15 =1 Then
glc_s = glc_s + (4*glc_x + 6)
Else
glc_s = glc_s + (4*(glc_x-glc_y) + 10)
glc_y = glc_y - 1
EndIf
glc_x = glc_x + 1
Wend
Return
'
drawline: ' draw any line to screen including diagonals
stepx = 0
stepy = 0
frac = 0
'line from start point x0,y0 to destination point x1,y1.
dy = y1 - y0
dx = x1 - x0
If dy > 128 Then
dy = 0 - dy
stepy = stepy - 1
Else
stepy = 1
EndIf
If dx > 128 Then
dx = 0 - dx
stepx = stepx - 1
Else
stepx = 1
EndIf
dy = dy << 1
dx = dx << 1
'draw pixel
px = x0 : py = y0
GoSub setpixel
If dx > dy Or dx > 128 Then
frac = dy - (dx >> 1)
While x0 != x1
If frac < 128 Then
y0 = y0 + stepy
frac = frac - dx
EndIf
x0 = x0 + stepx
frac = frac + dy
'draw pixel
px = x0 : py = y0
GoSub setpixel
Wend
Else
frac = dx - (dy >> 1)
While y0 != y1
If frac < 128 Then
x0 = x0 + stepx
frac = frac - dy
EndIf
y0 = y0 + stepy
frac = frac + dx
'draw pixel
px = x0 : py = y0
GoSub setpixel
Wend
EndIf
Return
'
Rotate: ' the only assembler routine
GoSub rota ' needed for speed
rota: ' by neglecting to carry the
GoSub RotateDisplay ' status bit, it also clears
GoSub RotateDisplay ' the buffer for the next frame
RotateDisplay: ' bitwise rotate array right
@ Rlf dis + 50 ,F ; ditching the first bit
@ Rlf dis+49 ,F ;
@ Rlf dis+48 ,F ;
@ Rlf dis+47 ,F ;
@ Rlf dis+46 ,F ;
@ Rlf dis+45 ,F ;
@ Rlf dis+44 ,F ;
@ Rlf dis+43 ,F ;
@ Rlf dis+42 ,F ;
@ Rlf dis+41 ,F ;
@ Rlf dis+40 ,F ;
@ Rlf dis+39 ,F ;
@ Rlf dis+38 ,F ;
@ Rlf dis+37 ,F ;
@ Rlf dis+36 ,F ;
@ Rlf dis+35 ,F ;
@ Rlf dis+34 ,F ;
@ Rlf dis+33 ,F ;
@ Rlf dis+32 ,F ;
@ Rlf dis+31 ,F ;
@ Rlf dis+30 ,F ;
@ Rlf dis+29 ,F ;
@ Rlf dis+28 ,F ;
@ Rlf dis+27 ,F ;
@ Rlf dis+26 ,F ;
@ Rlf dis+25 ,F ;
@ Rlf dis+24 ,F ;
@ Rlf dis+23 ,F ;
@ Rlf dis+22 ,F ;
@ Rlf dis+21 ,F ;
@ Rlf dis+20 ,F ;
@ Rlf dis+19 ,F ;
@ Rlf dis+18 ,F ;
@ Rlf dis+17 ,F ;
@ Rlf dis+16 ,F ;
@ Rlf dis+15 ,F ;
@ Rlf dis+14 ,F ;
@ Rlf dis+13 ,F ;
@ Rlf dis+12 ,F ;
@ Rlf dis+11 ,F ;
@ Rlf dis+10 ,F ;
@ Rlf dis+9 ,F ;
@ Rlf dis+8 ,F ;
@ Rlf dis+7 ,F ;
@ Rlf dis+6 ,F ;
@ Rlf dis+5 ,F ;
@ Rlf dis+4 ,F ;
@ Rlf dis+3 ,F ;
@ Rlf dis+2 ,F ;
@ Rlf dis+1 ,F ;
@ Rlf dis+0 ,F ;
@ Bcf dis+50 ,0 ;clear MSB
Return