Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions libraries/community/p2/All/isp_hub75_matrix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ Language: Spin2 / Pasm2

Created: 03-DEC-2020

Upadted: 19-FEB-2021

Category: display

Description:
Driver for HUB75 controlled RGB LED Matrix Panels

Related:

- See Docs, Setup Instructions at [HUB75 LED Matrix Driver Github Repository](https://github.com/ironsheep/p2-HUB75-LED-Matrix-Driver)
- Watch for P2 Eval HUB75 Driver Board soon to be for sale at [Parallax Shop](https://www.parallax.com/product-category/propeller-2/)
- See Docs, Setup Instructions at [HUB75 LED Matrix Driver Github Repository](https://github.com/ironsheep/p2-LED-Matrix-Driver)
- Buy P2 Eval HUB75 Driver Board at [Parallax Online Store](https://www.parallax.com/product/p2-eval-hub75-adapter-board/)
- See Morphing Digits software add-on at the [P2 LED-Matrix Morphing Digits Repository](https://github.com/ironsheep/P2-LED-Matrix-Morphing-Digits)

License: MIT (see end of source code)
26 changes: 23 additions & 3 deletions libraries/community/p2/All/isp_hub75_matrix/isp_hub75_color.spin2
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,27 @@ CON { test colorset }
cOrange = $FFA500
cBlueViolet = $8A2BE2

cFullRed = $FF0000
cFullGreen = $00FF00
cFullBlue = $0000FF

' SPECIAL non-colors - invoke alforithm to gerate actual color used'
cRedWhtBlu = $deadf0
cRainbow = $deadf1

#0, LED_UNKNOWN, LED_RED, LED_GREEN, LED_BLUE

' our 3-bit colors
BASE_BLACK = $00
BASE_RED = $01
BASE_GREEN = $02
BASE_YELLOW = $03
BASE_BLUE = $04
BASE_MAGENTA = $05
BASE_CYAN = $06
BASE_WHITE = $07


OBJ

screen : "isp_hub75_screenAccess"
Expand Down Expand Up @@ -152,14 +167,19 @@ PUB dutyCycleForIntensity(hex8bit) : pwmBits
'' CALCULATE: proper duty cycle for intensity of 0-255
' --- VERSION 1 - Bits spread throughout ---
if hex8bit == 255
pwmBits := $ff
pwmBits := screen.MAX_PWM_FRAMES
else
pwmBits := hex8bit / screen.MAX_PWM_FRAMES


{
if not didShow[hex8bit]
debug("clr:dcyc ", uhex_byte(hex8bit), uhex_byte(pwmBits))
didShow[hex8bit] := TRUE
'}

DAT { tables, default values }

didShow byte FALSE[256]

defaultBrightness word 256 '256 ' 205 = 80% [0-255,256] where 256 is NO brightness adjustment

' Gamma curve (lookup table)
Expand Down
Git LFS file not shown
120 changes: 85 additions & 35 deletions libraries/community/p2/All/isp_hub75_matrix/isp_hub75_display.spin2
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ SCROLL_FOREVER = scroller.SCROLL_FOREVER
SCROLL_ONCE = scroller.SCROLL_ONCE
SCROLL_ONCE_TO_CLEAR = scroller.SCROLL_ONCE_TO_CLEAR

' FIXME: UNDONE make this user configurable
MAX_SCROLLING_REGIONS = 3

DAT { one or more screens of pixels of 24bit color }
Expand Down Expand Up @@ -66,18 +67,31 @@ VAR { Object Instance Variables }
byte horizontalGapInPix
byte verticalGapInPix
byte hBitmapOffsetInPix
byte bScan_1_4
byte bSwapRB

PUB start() : ok | scrollerIndex
PUB start() : ok | scrollerIndex, dvrConfig, driverConfigRaw
'' Start the underlying driver(s)

ok := cog := -1 ' mark as failed, initially

'debug("`term temp size 80 50 textsize 10")
if screen.MAX_PANELS_PER_COLUMN * screen.MAX_PANELS_PER_ROW <> screen.MAX_PANELS
debug("dsp:Geometry BAD in isp_hub75_hwGeometry.spin2!")
abort


debug("- TEXT: start()")
debug("dsp:start()")
ok := cog := panel.start() ' send buffer to driver
if ok == -1
debug("- TEXT: underlying drivers failed!")
debug("dsp:underlying drivers failed!")
abort

dvrConfig, driverConfigRaw := screen.getDriverFlags()
bScan_1_4 := (dvrConfig & screen.SCAN_4) > 0 ? True : False
bSwapRB := (dvrConfig & screen.RB_SWAP) > 0 ? True : False


' tell all about location of screen buffer
screen.setScreen(@screen0)

Expand All @@ -104,18 +118,23 @@ PUB clearScreen()

PUB fillScreen(rgbColor) | row, column
'' Fill the display with 24-bit color value
repeat row from 0 to screen.MAX_DISPLAY_ROWS - 1
repeat column from 0 to screen.MAX_DISPLAY_COLUMNS - 1
repeat row from 0 to screen.MAX_PHYSICAL_ROWS - 1
repeat column from 0 to screen.MAX_PHYSICAL_COLUMNS - 1
pixels.drawPixelAtRC(row, column, rgbColor)

PUB fillPanel(threeBitColor)
'' Fill screen but without PWM (for testing underlying driver)
panel.fillPanel(threeBitColor)

PUB commitScreenToPanel()
'' Write sceen to panel driver
'debug("- DISP: commit!")
panel.convertScreen2PWM(@screen0)
'' Write sceen to panel driver PWM frames (while alternating PWM frame sets)
'debug("dsp: commit!")

if bScan_1_4
panel.convertScreen2PWM_14(@screen0, bSwapRB)
'panel.convertScreen2PWM_14_spin(@screen0, bSwapRB)
else
panel.convertScreen2PWM(@screen0, bSwapRB)


{ -------------- Text Handling -------------- }
Expand Down Expand Up @@ -185,7 +204,7 @@ PUB setTextFont(newFont) | scrollerIndex, hUnusedPix, vUnusedPix

selectedTextFont := newFont

debug("dsp:font ", udec(charHeightInPix), udec(charWidthInPix), udec(maxTextLines), udec(maxTextColumns), udec(verticalGapInPix), udec(horizontalGapInPix), udec(topOffsetInPix), udec(leftOffsetInPix))
'debug("dsp:font ", udec(charHeightInPix), udec(charWidthInPix), udec(maxTextLines), udec(maxTextColumns), udec(verticalGapInPix), udec(horizontalGapInPix), udec(topOffsetInPix), udec(leftOffsetInPix))

' configure our scrollers for font choice
repeat scrollerIndex from 0 to MAX_SCROLLING_REGIONS - 1
Expand Down Expand Up @@ -310,7 +329,7 @@ PRI nextFreeScroller() : scrollerIndexToUse | scrollerIndex
if scrollerIndexToUse == NOT_FOUND
debug("Failed to locate free scroller!")
abort
debug("dsp:nextFreeScroller() ", udec(scrollerIndexToUse))
'debug("dsp:nextFreeScroller() ", udec(scrollerIndexToUse))

{ -------------- Basic Graphics -------------- }

Expand All @@ -324,25 +343,25 @@ PUB drawBoxOfColor(topRow, leftColumn, width, height, filled, rgbColor) | rightC
bottomRow := topRow + height - 1
if filled == TRUE
repeat rowIndex from 0 to height - 1
drawLineOfColor(topRow + rowIndex, leftColumn, topRow + rowIndex, rightColumn, currTextColor) ' horiz row
drawLineOfColor(topRow + rowIndex, leftColumn, topRow + rowIndex, rightColumn, rgbColor) ' horiz row
else
drawLineOfColor(topRow, leftColumn, topRow, rightColumn, currTextColor) ' horiz top
drawLineOfColor(topRow, rightColumn, bottomRow, rightColumn, currTextColor) ' vert right
drawLineOfColor(bottomRow, leftColumn, bottomRow, rightColumn, currTextColor) ' horiz bottom
drawLineOfColor(topRow, leftColumn, bottomRow, leftColumn, currTextColor) ' vert left
drawLineOfColor(topRow, leftColumn, topRow, rightColumn, rgbColor) ' horiz top
drawLineOfColor(topRow, rightColumn, bottomRow, rightColumn, rgbColor) ' vert right
drawLineOfColor(bottomRow, leftColumn, bottomRow, rightColumn, rgbColor) ' horiz bottom
drawLineOfColor(topRow, leftColumn, bottomRow, leftColumn, rgbColor) ' vert left


PUB drawLine(fmRow, fmColumn, toRow, toColumn)
'' Draw line fromRC -> toRC using current text color (currently limited to horzontal/vertical lines)
drawLineOfColor(fmRow, fmColumn, toRow, toColumn, currTextColor)

PUB drawLineOfColor(fmRow, fmColumn, toRow, toColumn, rgbColor) | row, column, dx, dy, ctr, incr
PUB drawLineOfColor(fmRow, fmColumn, toRow, toColumn, rgbColor) | row, column, dx, dy, ctr, incr, intD
'' Draw line fromRC -> toRC using rgbColor (currently limited to horzontal/vertical lines)
fmRow := 0 #> fmRow <# screen.MAX_PHYSICAL_ROWS - 1
fmColumn := 0 #> fmColumn <# screen.MAX_PHYSICAL_COLUMNS - 1
toRow := 0 #> toRow <# screen.MAX_PHYSICAL_ROWS - 1
toColumn := 0 #> toColumn <# screen.MAX_PHYSICAL_COLUMNS - 1
'debug("seg:drwLn fmRC=(", udec_(fmRow), ",", udec_(fmColumn), "), toRC=(", udec_(toRow), ",", udec_(toColumn), "), RGB=(", uhex_long(rgbColor), ")")
fmRow := 0 #> fmRow <# screen.MAX_DISPLAY_ROWS - 1
fmColumn := 0 #> fmColumn <# screen.MAX_DISPLAY_COLUMNS - 1
toRow := 0 #> toRow <# screen.MAX_DISPLAY_ROWS - 1
toColumn := 0 #> toColumn <# screen.MAX_DISPLAY_COLUMNS - 1
if fmRow == toRow
' draw Horizontal Line
repeat column from fmColumn to toColumn
Expand All @@ -352,22 +371,53 @@ PUB drawLineOfColor(fmRow, fmColumn, toRow, toColumn, rgbColor) | row, column, d
repeat row from fmRow to toRow
pixels.drawPixelAtRC(row, fmColumn, rgbColor)
else
dx := (toColumn - fmColumn)
dy := (toRow - fmRow)
if (abs(dx) >= abs(dy))
incr := abs(dx)
if abs(toRow - fmRow) < abs(toColumn - fmColumn)
if fmColumn > toColumn
plotLineLow(toColumn, toRow, fmColumn, fmRow, rgbColor)
else
plotLineLow(fmColumn, fmRow, toColumn, toRow, rgbColor)
else
incr := abs(dy)
dx := dx / incr
dy := dy / incr
column := fmColumn
row := fmRow
ctr := 1
repeat while (ctr <= incr)
pixels.drawPixelAtRC(row, column, rgbColor)
column += dx
row += dy
ctr += 1
if fmRow > toRow
plotLineHigh(toColumn, toRow, fmColumn, fmRow, rgbColor)
else
plotLineHigh(fmColumn, fmRow, toColumn, toRow, rgbColor)


PRI plotLineLow(x0, y0, x1, y1, rgbColor) | row, column, dy, dx, D, yi
dx := x1 - x0
dy := y1 - y0
yi := 1
if dy < 0
yi := -1
dy := -dy
D := (2 * dy) - dx
row := y0

repeat column from x0 to x1
pixels.drawPixelAtRC(row, column, rgbColor)
if D > 0
row := row + yi
D := D + (2 * (dy - dx))
else
D := D + 2 * dy

PRI plotLineHigh(x0, y0, x1, y1, rgbColor) | row, column, dy, dx, D, xi
dx := x1 - x0
dy := y1 - y0
xi := 1
if dx < 0
xi := -1
dx := -dx
D := (2 * dx) - dy
column := x0

repeat row from y0 to y1
pixels.drawPixelAtRC(row, column, rgbColor)
if D > 0
column := column + xi
D := D + (2 * (dx - dy))
else
D := D + 2*dx

{ -------------- Misc Helpers -------------- }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ PRI loadBitmap(pBitmapFile) | nPanelCol, nPanelRow, blue, green, red, haveError,
abort

' fill screen buffer
repeat nPanelRow from 0 to screen.MAX_PANEL_ROWS - 1
repeat nPanelCol from 0 to screen.MAX_PANEL_COLUMNS - 1
repeat nPanelRow from 0 to screen.MAX_PHYSICAL_ROWS - 1
repeat nPanelCol from 0 to screen.MAX_PHYSICAL_COLUMNS - 1
'debug("loadBitmap() - RC=(", udec_(nPanelRow), ", ", udec_(nPanelCol), ")")
showDebug := FALSE
if isDebugLocn(nPanelRow, nPanelCol)
Expand Down Expand Up @@ -101,7 +101,7 @@ PRI validateBmpFile(pBmpFileImage) : bValidStatus | pFileHeader, i, iStart, iEnd
' XYZZYpnl debug(" - Img-start @0x", uhex_(iStart))
' XYZZYpnl debug(" - Img-end @0x", uhex_(iEnd))

if biWidth <> screen.MAX_PANEL_COLUMNS or biHeight <> screen.MAX_PANEL_ROWS
if biWidth <> screen.MAX_PHYSICAL_COLUMNS or biHeight <> screen.MAX_PHYSICAL_ROWS
' XYZZYpnl debug(" !! invalid BMP size! [NOT 64x32]")
bValidStatus := FALSE

Expand All @@ -118,16 +118,16 @@ PRI validateBmpFile(pBmpFileImage) : bValidStatus | pFileHeader, i, iStart, iEnd
'else
' XYZZYpnl debug("-good BMP size! [64x32]")

'dbgMemDump(@fileHeaderMsg, pBmpFileImage, bfOffBits)
'dbgMemDump(@fileStartMsg, iStart, 32)
'dbgMemDump(@fileEndMsg, iEnd-32-1, 32)
'screen.dbgMemDump(@fileHeaderMsg, pBmpFileImage, bfOffBits)
'screen.dbgMemDump(@fileStartMsg, iStart, 32)
'screen.dbgMemDump(@fileEndMsg, iEnd-32-1, 32)

PRI get24BitBMPColorForRC(nRow, nColumn) : red, green, blue | pixColorAddr
if(nRow > screen.MAX_PANEL_ROWS - 1)
debug("- ERROR bad nRow value [", udec_(nRow), " > ", udec_(screen.MAX_PANEL_ROWS - 1), "]")
if(nRow > screen.MAX_PHYSICAL_ROWS - 1)
debug("- ERROR bad nRow value [", udec_(nRow), " > ", udec_(screen.MAX_PHYSICAL_ROWS - 1), "]")

if(nColumn > screen.MAX_PANEL_COLUMNS - 1)
debug("- ERROR bad nColumn value [", udec_(nColumn), " > ", udec_(screen.MAX_PANEL_COLUMNS - 1), "]")
if(nColumn > screen.MAX_PHYSICAL_COLUMNS - 1)
debug("- ERROR bad nColumn value [", udec_(nColumn), " > ", udec_(screen.MAX_PHYSICAL_COLUMNS - 1), "]")

pixColorAddr := getPixelAddressForBMPRowColumn(nRow, nColumn)
' our intername .bmp file byte order is BGR!
Expand All @@ -137,7 +137,7 @@ PRI get24BitBMPColorForRC(nRow, nColumn) : red, green, blue | pixColorAddr

PRI getPixelAddressForBMPRowColumn(nRow, nColumn) : pixColorAddr | rowIndex, columnIndex, nOffset, fileBitsBase, showDebug
' Row is inverted in .BMP file...
rowIndex := (screen.MAX_PANEL_ROWS - 1) - nRow
rowIndex := (screen.MAX_PHYSICAL_ROWS - 1) - nRow

' Column is normal in file...
columnIndex := nColumn
Expand All @@ -148,7 +148,7 @@ PRI getPixelAddressForBMPRowColumn(nRow, nColumn) : pixColorAddr | rowIndex, col
showDebug := TRUE ' FALSE ' turn off debug

' now offset is simple (just multiply by 3! [bytes of color])
nOffset := ((rowIndex * screen.MAX_PANEL_COLUMNS) + columnIndex) * screen.DISPLAY_BYTES_PER_COLOR
nOffset := ((rowIndex * screen.MAX_PHYSICAL_COLUMNS) + columnIndex) * screen.DISPLAY_BYTES_PER_COLOR

fileBitsBase := @byte[pBitmapFileInMemory][bfOffBits] ' get base of image in file (skip header)
pixColorAddr := @byte[fileBitsBase][nOffset] ' add in offset to 24-bit color
Expand Down
Loading