diff --git a/driver/TstBG-Up.bmp b/driver/TstBG-Up.bmp new file mode 100644 index 0000000..94713ae Binary files /dev/null and b/driver/TstBG-Up.bmp differ diff --git a/driver/TstBGCol.bmp b/driver/TstBGCol.bmp new file mode 100644 index 0000000..1250354 Binary files /dev/null and b/driver/TstBGCol.bmp differ diff --git a/driver/isp_hub75_7seg.spin2 b/driver/isp_hub75_7seg.spin2 index d04b2be..dff2a70 100644 --- a/driver/isp_hub75_7seg.spin2 +++ b/driver/isp_hub75_7seg.spin2 @@ -39,13 +39,13 @@ segmentsByDigit byte %0111_1011 ' 9 abcd-fg VAR { globals } - long currValue + long currValue long currRgbColor long topY long leftX long defaultColor - + byte isSetup PUB null() @@ -65,20 +65,20 @@ PUB placeDigit(row, column, digit, rgbColor) if digit <> DIGIT_HIDDEN reconfigureForDigit(digit) -PUB setValue(digit) +PUB setValue(digit) '' Configure display to show desired {digit}: [0-9, DIGIT_HIDDEN] ensureIsSetup() if currValue <> digit reconfigureForDigit(digit) PUB incrementValue(shouldWrap) | nextValue - '' Increment to the next digit [0->9] + '' Increment to the next digit [0->9] '' if wrap is requested, return to 0 after 9, else just stop at 9 nextValue := currValue + 1 - if nextValue > 9 + if nextValue > 9 if shouldWrap <> WITH_WRAP nextValue := 9 - else + else nextValue := 0 setValue(nextValue) @@ -135,7 +135,7 @@ PRI initialSetup() | segIndex, orientation, segRow, segCol 0: ' G MIDDLE orientation := segments.SEG_MIDDLE segRow := topY + 1 + segments.SEG_LENGTH + 0 - 1 - segCol := leftX + 1 + segCol := leftX + 1 segments[segIndex].placeSegment(segRow, segCol, orientation, segments.STATE_OFF, currRgbColor) @@ -156,15 +156,15 @@ PRI reconfigureForDigit(digit) | byte fromSegments, byte toSegments, bitIndex if toSegments & (1 << bitIndex) > 0 ' to segment should be showing ' NO CHANGE - else + else ' to segment should be hidden segments[bitIndex].moveSegmentToState(segments.STATE_OFF) - else + else ' from segment is hidden if toSegments & (1 << bitIndex) > 0 ' to segment should be showing segments[bitIndex].moveSegmentToState(segments.STATE_ON) - else + else ' to segment should be hidden ' NO CHANGE else @@ -200,4 +200,3 @@ CON { license } SOFTWARE. ================================================================================================= }} - diff --git a/driver/isp_hub75_color.spin2 b/driver/isp_hub75_color.spin2 index 7a852d1..74aec42 100644 --- a/driver/isp_hub75_color.spin2 +++ b/driver/isp_hub75_color.spin2 @@ -6,13 +6,13 @@ '' -- Copyright (c) 2020 Iron Sheep Productions, LLC '' -- see below for terms of use '' E-mail..... stephen@ironsheep.biz -'' Started.... Oct 2020 +'' Started.... Oct 2020 '' Updated.... 24 Oct 2020 '' '' ================================================================================================= CON { test colorset } - + cBlack = $000000 cWhite = $FFFFFF cRed = $FF0000 @@ -32,7 +32,7 @@ CON { test colorset } cDarkGreen = $006400 cOrange = $FFA500 cBlueViolet = $8A2BE2 - + ' SPECIAL non-colors - invoke alforithm to gerate actual color used' cRedWhtBlu = $deadf0 cRainbow = $deadf1 @@ -130,30 +130,10 @@ PUB rgbColorFromDegrees(degrees) : rcbColor | offset60, fract60, red, green, blu elseif degrees >= 60 green := 255 red := ((59 - offset60) * fract60) / 100 - else + else red := 255 green := (offset60 * fract60) / 100 - { - fract60 := 4.25 ' float(255 / 60) ' 4.25 ' 255 / 60 - if degrees >= 300 - red := 255 - blue := (59 - offset60) * fract60 - elseif degrees >= 240 - blue := 255 - red := offset60 * fract60 - elseif degrees >= 180 - blue := 255 - green := (59 - offset60) * fract60 - elseif degrees >= 120 - green := 255 - blue := offset60 * fract60 - elseif degrees >= 60 - green := 255 - red := (59 - offset60) * fract60 - else - red := 255 - green := offset60 * fract60 - } + rcbColor := cValueForRGB(red, green, blue) 'debug("- degrees=", udec_(degrees), ", color=", uhex_long_(rcbColor), " RGB=", udec_(red), ", ", udec_(green), ", ", udec_(blue), ")" ) @@ -168,46 +148,8 @@ PUB cValueForRGB(red, green, blue) : combinedValue '' CONVERT: r,g,b to combined value combinedValue := ((red & $ff) << 16) | ((green & $ff) << 8) | (blue & $ff) -PRI dutyCycleForIntensityOld1(hex8bit) : pwmBits - ' CALCULATE: proper duty cycle for intensity of 0-255 - ' --- VERSION 1 - Bits spread throughout --- - if hex8bit == 255 - pwmBits := $ff - elseif hex8bit == 0 - pwmBits := $00 - else - pwmBits := (hex8bit / screen.MAX_PWM_FRAMES - 1) + 1 - -PRI dutyCycleForIntensityOld2(hex8bit) : pwmBits | segmentSize - ' CALCULATE: proper duty cycle for intensity of 0-255 - ' --- VERSION 2 - 3/4 high, 1/4 off, rest spread throughout --- - segmentSize := (256 / (screen.MAX_PWM_FRAMES + 1)) / 8 - if hex8bit >= 255 - ((segmentSize * 6) - 1) - pwmBits := $ff - elseif hex8bit <= (segmentSize * 2)- 1 - pwmBits := $00 - else - pwmBits := (hex8bit / screen.MAX_PWM_FRAMES) + 1 - -PRI dutyCycleForIntensityOld3(hex8bit) : pwmBits | segmentSize - ' WAIT!!! Pastel colors!???! - ' CALCULATE: proper duty cycle for intensity of 0-255 - ' --- VERSION 3 - Bits spread throughout --- - pwmBits := (hex8bit / screen.MAX_PWM_FRAMES + 1) - -PRI dutyCycleForIntensityOld4(hex8bit) : pwmBits | segmentSize - ' CALCULATE: proper duty cycle for intensity of 0-255 - ' --- VERSION 4 - 2/6 high, 1/6 off, rest spread throughout --- - segmentSize := ((256 / (screen.MAX_PWM_FRAMES + 1)) / 2) / 3 - if hex8bit >= 255 - (segmentSize * 2) + 1 - pwmBits := $ff - elseif hex8bit <= 0 + segmentSize - 1 - pwmBits := $00 - else - pwmBits := ((hex8bit * 10854) / screen.MAX_PWM_FRAMES) / 10000 - -PRI dutyCycleForIntensity(hex8bit) : pwmBits - ' CALCULATE: proper duty cycle for intensity of 0-255 +PUB dutyCycleForIntensity(hex8bit) : pwmBits + '' CALCULATE: proper duty cycle for intensity of 0-255 ' --- VERSION 1 - Bits spread throughout --- if hex8bit == 255 pwmBits := $ff @@ -257,7 +199,7 @@ gammaOld byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 byte 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 197, 199, 201, 203, 205 byte 207, 210, 212, 214, 216, 219, 221, 223, 226, 228, 230, 233, 235, 237, 240, 242, 245 byte 247, 250, 252, 255 - + gamma2_0 ' 256-step brightness table: gamma = 2.0 byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 @@ -401,4 +343,3 @@ CON { license } SOFTWARE. ================================================================================================= }} - diff --git a/driver/isp_hub75_demo7seg.spin2 b/driver/isp_hub75_demo7seg.spin2 index 5674690..6f4624f 100644 --- a/driver/isp_hub75_demo7seg.spin2 +++ b/driver/isp_hub75_demo7seg.spin2 @@ -54,7 +54,7 @@ PUB start() : ok | blockX, blockY, subrow, subcol, row, col, red, green, blue, b digitPeriod := 12 ' 90 ' 4 x 100ths of a second ' draw some text! - display.setTextFont(display.TEXT_FONT_5x7) ' font size + display.setTextFont(display.TEXT_FONT_5x7) ' font size display.setCursor(0, 0) ' start at top left, with one pixel of spacing @@ -93,8 +93,8 @@ PUB start() : ok | blockX, blockY, subrow, subcol, row, col, red, green, blue, b loopUntilSegmentsFinish() - wait100thSecs(digitPeriod) - + wait100thSecs(digitPeriod) + { ' transitional DEMO @@ -121,7 +121,7 @@ PUB start() : ok | blockX, blockY, subrow, subcol, row, col, red, green, blue, b loopUntilSegmentsFinish() - wait100thSecs(digitPeriod) + wait100thSecs(digitPeriod) } @@ -132,7 +132,7 @@ PRI showSecondsDots(lightDark) | red, green, blue, targetColor ' lightDarkv[0,1] where 1 means bright color if lightDark == 0 targetColor := $00006F - else + else targetColor := $0080FF drawSecondsDot(15, 31, targetColor) @@ -154,15 +154,15 @@ PRI allDigitAnimationsComplete() : status PRI loopUntilSegmentsFinish() - repeat - if not allDigitAnimationsComplete() + repeat + if not allDigitAnimationsComplete() repeat digitIndex from 0 to 3 if not digit[digitIndex].isAnimationComplete() - digit[digitIndex].animateStep() + digit[digitIndex].animateStep() display.commitScreenToPanel() wait100thSecs(segmentPeriod) - if allDigitAnimationsComplete() + if allDigitAnimationsComplete() quit PUB wait100thSecs(count) @@ -171,7 +171,7 @@ PUB wait100thSecs(count) waitms(10) ' 1/100 seconds -PUB stop() +PUB stop() '' Stop the driver if cog display.stop() @@ -206,4 +206,3 @@ CON { license } SOFTWARE. ================================================================================================= }} - diff --git a/driver/isp_hub75_demoColor.spin2 b/driver/isp_hub75_demoColor.spin2 index 5a834b5..0b0e57d 100644 --- a/driver/isp_hub75_demoColor.spin2 +++ b/driver/isp_hub75_demoColor.spin2 @@ -7,7 +7,7 @@ '' -- see below for terms of use '' E-mail..... stephen@ironsheep.biz '' Started.... Oct 2020 -'' Updated.... 17 Oct 2020 +'' Updated.... 01 Dec 2020 '' '' ================================================================================================= @@ -34,6 +34,7 @@ OBJ pixels : "isp_hub75_screenUtils" screen : "isp_hub75_screenAccess" display : "isp_hub75_display" + bmpHandler : "isp_hub75_display_bmp" PUB main() : ok | demoIndex '' start underlying drivers and run demo @@ -46,52 +47,26 @@ PUB main() : ok | demoIndex if ok == -1 debug("- DEMO: underlying drivers failed!") abort -{ - demoIndex := 0 - 'repeat - repeat demoIndex from 0 to 5 - display.clearScreen() - case demoIndex - 0: demoTest256ColorBrightness() - 1: demoTest32ColorBrightness() - 2: demoTest16ColorBrightness() - 3: demoTest360ColorBrightness() - 4: demoTestGammaTuneBrightness() - 5: demoTest12x9ColorBrightness() - waitSec(5) - repeat -'} -{ - demoTest12x9ColorBrightness() - repeat -'} - 'demoColorPalette12Panels() - 'demoScreenBlastRed() - 'repeat - 'demoScreenBlastWhite() - 'repeat -{ - demoAlignmentText() - repeat -'} + demoPausePeriod := 3 ' seconds + repeat 20 repeat demoIndex from 0 to DEMO_COUNT - 1 display.clearScreen() case demoIndex + 1 1: demoText() 2: demoParallax() - 3: demoColorBrightness() - 4: demoHueGroups() ' needs fixing - 5: demoHueLines() - 6: demoColorPalette12Panels() - 7: showFullColorSweep() - 8: demoTest12x9ColorBrightness() - 9: colorBlast() - 10: demoText() - 11: demoScreenBlast() - - if demoIndex + 1 <> 11 + 3: demoHueGroups() ' needs fixing + 4: demoHueLines() + 5: demoColorPalette12Panels() + 6: showFullColorSweep() + 7: demoTest12x9ColorBrightness() + 8: colorBlast() + 9: demoText() + 10: demoScreenBlast() + 11: demoBmpFileLoad() + + if demoIndex + 1 <> 10 waitSec(demoPausePeriod) stop() @@ -109,7 +84,7 @@ PRI waitSec(countSeconds) ' do DEMO Things! PRI demoParallax() | rtCol, ltCol, topRow, botRow - display.setTextFont(display.TEXT_FONT_5x7) ' font size + display.setTextFont(display.TEXT_FONT_5x7) ' font size display.setCursor(0, 0) ' start at top left, with one pixel of spacing ltCol := 0 @@ -126,7 +101,7 @@ PRI demoParallax() | rtCol, ltCol, topRow, botRow display.commitScreenToPanel() PRI demoAlignmentText() - display.setTextFont(display.TEXT_FONT_5x7) ' font size + display.setTextFont(display.TEXT_FONT_5x7) ' font size display.setCursor(0, 0) ' start at top left, with one pixel of spacing display.setColoredTextAtLnCol(0, 0, string("Line 1"), color.cBlue) display.setColoredTextAtLnCol(1, 0, string("Propeller"), color.cBlue) @@ -136,7 +111,7 @@ PRI demoAlignmentText() PRI demoText() ' draw some text! - display.setTextFont(display.TEXT_FONT_5x7) ' font size + display.setTextFont(display.TEXT_FONT_5x7) ' font size display.setCursor(0, 0) ' start at top left, with one pixel of spacing display.setColoredTextAtLnCol(0,0, string("iron sheep"), color.cMaroon) @@ -481,9 +456,9 @@ PRI demoColorBrightness() | red, green, blue, row, col, rowCtr, colorIndex, useR 'repeat ' hold here! - + PRI demoHueLines() | row, col, colorOffset - ' COLOR PANEL using hue - all in one line + ' COLOR PANEL using hue - all in one line col := 2 repeat row from 0 to 31 repeat colorOffset from 0 to 350 step 6 @@ -494,7 +469,7 @@ PRI demoHueLines() | row, col, colorOffset display.commitScreenToPanel() PRI demoHueLinesToo() | row, col, colorOffset - ' COLOR PANEL using hue - all in one line + ' COLOR PANEL using hue - all in one line col := 0 repeat row from 0 to 31 repeat colorOffset from 0 to 350 step 6 @@ -649,6 +624,15 @@ PRI demoScreenBlastWhite() | color3bit color3bit := 7 display.fillPanel(color3bit) +PRI demoBmpFileLoad() + + bmpHandler.fillScreenFromBMP(@bmpFile1) + display.commitScreenToPanel() + +DAT + +'bmpFile1 FILE "TstBGCol.bmp" +bmpFile1 FILE "TstBG-Up.bmp" CON { license } @@ -679,4 +663,3 @@ CON { license } SOFTWARE. ================================================================================================= }} - diff --git a/driver/isp_hub75_display.spin2 b/driver/isp_hub75_display.spin2 index 1dddbe4..9b6bb5d 100644 --- a/driver/isp_hub75_display.spin2 +++ b/driver/isp_hub75_display.spin2 @@ -7,7 +7,7 @@ '' -- see below for terms of use '' E-mail..... stephen@ironsheep.biz '' Started.... Oct 2020 -'' Updated.... 17 Oct 2020 +'' Updated.... 01 Dec 2020 '' '' ================================================================================================= @@ -115,7 +115,7 @@ PUB fillPanel(threeBitColor) PUB commitScreenToPanel() '' Write sceen to panel driver 'debug("- DISP: commit!") - panel.loadScreen(@screen0) + panel.convertScreen2PWM(@screen0) { -------------- Text Handling -------------- } @@ -125,13 +125,13 @@ PUB setCursor(line, column) ' TODO emit error on bad column/row? cursorLine := 0 #> line <# maxTextLines - 1 cursorColumn := 0 #> column <# maxTextColumns - 1 - + PUB homeCursor() '' Return the cursor to top left corner of our display setCursor(0, 0) PUB setTextFont(newFont) | scrollerIndex, hUnusedPix, vUnusedPix - '' Select font and update text grid size + '' Select font and update text grid size ' currently we only support our 8x8 and 5x7 fonts case newFont TEXT_FONT_DEFAULT..TEXT_FONT_5x7: @@ -191,11 +191,11 @@ PUB setTextFont(newFont) | scrollerIndex, hUnusedPix, vUnusedPix repeat scrollerIndex from 0 to MAX_SCROLLING_REGIONS - 1 scroller[scrollerIndex].setFontInfo(maxTextColumns, charWidthInPix, charHeightInPix, leftOffsetInPix, horizontalGapInPix, hBitmapOffsetInPix, selectedTextFont) -PUB setTextColor(rgbColor) +PUB setTextColor(rgbColor) '' Set 24-bit color for subsequent text display currTextColor := rgbColor -PUB setTextAtCursor(zString) +PUB setTextAtCursor(zString) '' Place text 'zero terminated' at our current cursor position using current text color setColoredTextAtLnCol(cursorLine, cursorColumn, zString, currTextColor) @@ -203,7 +203,7 @@ PUB setColoredTextAtLnCol(line, column, pString, rgbColor) | charIndex '' Place text at specific cursor position using current text color setCursor(line, column) charIndex := 0 - repeat + repeat if byte[pString][charIndex] <> 0 setColorCharAtCursor(byte[pString][charIndex++], rgbColor) while byte[pString][charIndex] <> 0 @@ -254,7 +254,7 @@ PUB scrollText(indexAllocated, loopCount) scroller[indexAllocated].scrollText(loopCount) -PUB scrollTextOnLine(line, pZString, direction) : indexAllocated +PUB scrollTextOnLine(line, pZString, direction) : indexAllocated '' Place scolling text on line N, of pZString scrolling in direction using current text color indexAllocated := scrollColoredTextOnLn(line, pZString, direction, currTextColor) @@ -274,7 +274,7 @@ PUB scrollColoredTextOnLn(line, pZString, direction, rgbColor) : indexAllocated indexAllocated := scrollTextAtRCOfColor(sRowPixIndex, sColumnPixIndex, widthInChars, pZString, direction, rgbColor) -PUB scrollTextAtRC(row, column, widthInChars, pZString, direction) : indexAllocated +PUB scrollTextAtRC(row, column, widthInChars, pZString, direction) : indexAllocated '' Place scolling text at absolute R,C, of pZString scrolling in direction using current text color indexAllocated := scrollTextAtRCOfColor(row, column, widthInChars, pZString, direction, currTextColor) @@ -345,11 +345,11 @@ PUB drawLineOfColor(fmRow, fmColumn, toRow, toColumn, rgbColor) | row, column, d toColumn := 0 #> toColumn <# screen.MAX_DISPLAY_COLUMNS - 1 if fmRow == toRow ' draw Horizontal Line - repeat column from fmColumn to toColumn + repeat column from fmColumn to toColumn pixels.drawPixelAtRC(fmRow, column, rgbColor) elseif fmColumn == toColumn ' draw Vertical Line - repeat row from fmRow to toRow + repeat row from fmRow to toRow pixels.drawPixelAtRC(row, fmColumn, rgbColor) else dx := (toColumn - fmColumn) @@ -363,7 +363,7 @@ PUB drawLineOfColor(fmRow, fmColumn, toRow, toColumn, rgbColor) | row, column, d column := fmColumn row := fmRow ctr := 1 - repeat while (ctr <= incr) + repeat while (ctr <= incr) pixels.drawPixelAtRC(row, column, rgbColor) column += dx row += dy @@ -390,7 +390,6 @@ PRI isDebugLocn(nRow, nCol) : status status := TRUE ' FALSE ' turn off debug - CON { license } {{ @@ -419,6 +418,5 @@ CON { license } OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================================= - -}} +}} diff --git a/driver/isp_hub75_display_bmp.spin2 b/driver/isp_hub75_display_bmp.spin2 new file mode 100644 index 0000000..0595ef0 --- /dev/null +++ b/driver/isp_hub75_display_bmp.spin2 @@ -0,0 +1,228 @@ +'' ================================================================================================= +'' +'' File....... isp_hub75_display_bmp.spin2 +'' Purpose.... Display contents of .bmp file on HUB75 RGB Matrix +'' Authors.... Stephen M Moraco +'' -- Copyright (c) 2020 Iron Sheep Productions, LLC +'' -- see below for terms of use +'' E-mail..... stephen@ironsheep.biz +'' Started.... Dec 2020 +'' Updated.... 01 Dec 2020 +'' +'' This object adds .bmp file loading support +'' ================================================================================================= + +OBJ { Objects Used by this Object } + + screen : "isp_hub75_screenAccess" + pixels : "isp_hub75_screenUtils" + color : "isp_hub75_color" + +VAR { buffer addresses } + + long pBitmapFileInMemory + +PUB null() + '' This is NOT a top level object + +PUB fillScreenFromBMP(pBmpFile) + '' Load a 24-bit .bmp file image into screen buffer (panel sized, only!) + loadBitmap(pBmpFile) + +PRI loadBitmap(pBitmapFile) | nPanelCol, nPanelRow, blue, green, red, haveError, showDebug, bInvalidFileStatus + ' Load a 24-bit .bmp file image into screen buffer + ' HEADS UP!!! + ' this is currently limited to "single panel size" untill we rerite this code + + ' save address of 24bit file image for use by called routines + pBitmapFileInMemory := pBitmapFile + + ' XYZZYpnl debug("- Study BMP") + bInvalidFileStatus := validateBmpFile(pBitmapFile) + if bInvalidFileStatus == FALSE + ' TODO: how do we warn of this? + abort + + ' fill screen buffer + repeat nPanelRow from 0 to screen.MAX_PANEL_ROWS - 1 + repeat nPanelCol from 0 to screen.MAX_PANEL_COLUMNS - 1 + 'debug("loadBitmap() - RC=(", udec_(nPanelRow), ", ", udec_(nPanelCol), ")") + showDebug := FALSE + if isDebugLocn(nPanelRow, nPanelCol) + showDebug := TRUE ' FALSE ' turn off debug + + red, green, blue := get24BitBMPColorForRC(nPanelRow, nPanelCol) + + if showDebug + ' XYZZYpnl debug(" - RC=(", udec_(nPanelRow), ", ", udec_(nPanelCol), "), RGB=(", uhex_(red), uhex_(green), uhex_(blue), ")") + + pixels.drawPixelAtRC(nPanelRow, nPanelCol, color.cValueForRGB(red, green, blue)) + +PRI validateBmpFile(pBmpFileImage) : bValidStatus | pFileHeader, i, iStart, iEnd, pLastByte + ' interpret .BMP header and return pointer to image + + ' XYZZYpnl debug("- Studying in-memory file") + bValidStatus := TRUE + 'analyze bitmap image + pFileHeader := pBmpFileImage + bytemove(@bfType, pFileHeader, 2) 'read bmp header + pFileHeader += 2 + bytemove(@bfSize, pFileHeader, 4) 'read bmp header + pFileHeader += 4 + bytemove(@bfReserved1, pFileHeader, 4) 'read bmp header + pFileHeader += 4 + bytemove(@bfOffBits, pFileHeader, 16) 'read bmp header + pFileHeader += 16 + bytemove(@biPlanes, pFileHeader, 4) + pFileHeader += 4 + bytemove(@biCompression, pFileHeader, 24) + pFileHeader += 24 + + 'calculate actual bytes in palette + i := bfOffBits - 54 + pFileHeader += i + + iStart := pBmpFileImage + bfOffBits + iEnd := iStart + biSizeImage - 1 + + ' return pointer to last byte in bitmap + pLastByte := pFileHeader + (biHeight * biWidth * 3) - 1 + + ' XYZZYpnl debug("BitMap file @0x", uhex_(pBmpFileImage)) + ' XYZZYpnl debug(" - size=", udec_(bfSize)) + ' XYZZYpnl debug(" - OffsetBits=", udec_(bfOffBits)) + 'debug(" - #planes=", udec_(biPlanes)) + ' XYZZYpnl debug(" - w,h=", udec_(biWidth), ",", udec_(biHeight)) + ' XYZZYpnl debug(" - szImage=", udec_(biSizeImage)) + 'debug(" - compression=", udec_(biCompression)) + ' XYZZYpnl debug(" - bitCount=", udec_(biBitCount)) + ' XYZZYpnl debug(" - end @0x", uhex_(pLastByte)) + + ' 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 + ' XYZZYpnl debug(" !! invalid BMP size! [NOT 64x32]") + bValidStatus := FALSE + + if byte[@bfType][0] <> $42 || byte[@bfType][1] <> $4d ' B, M + ' XYZZYpnl debug(" !! invalid BMP file type! [NOT 'BM']") + bValidStatus := FALSE + + if biCompression <> 0 + ' XYZZYpnl debug(" !! invalid BMP compression! [is compressed]") + bValidStatus := FALSE + + 'if bValidStatus == FALSE + ' XYZZYpnl debug("- ERROR invalid BMP!") + 'else + ' XYZZYpnl debug("-good BMP size! [64x32]") + + 'dbgMemDump(@fileHeaderMsg, pBmpFileImage, bfOffBits) + 'dbgMemDump(@fileStartMsg, iStart, 32) + '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(nColumn > screen.MAX_PANEL_COLUMNS - 1) + debug("- ERROR bad nColumn value [", udec_(nColumn), " > ", udec_(screen.MAX_PANEL_COLUMNS - 1), "]") + + pixColorAddr := getPixelAddressForBMPRowColumn(nRow, nColumn) + ' our intername .bmp file byte order is BGR! + blue := byte[pixColorAddr][0] + green := byte[pixColorAddr][1] + red := byte[pixColorAddr][2] + +PRI getPixelAddressForBMPRowColumn(nRow, nColumn) : pixColorAddr | rowIndex, columnIndex, nOffset, fileBitsBase, showDebug + ' Row is inverted in .BMP file... + rowIndex := (screen.MAX_PANEL_ROWS - 1) - nRow + + ' Column is normal in file... + columnIndex := nColumn + + showDebug := FALSE + 'if (bitIdx == 0 || bitIdx == 31) && nBffrR < 2 + if isDebugLocn(nRow, nColumn) + 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 + + fileBitsBase := @byte[pBitmapFileInMemory][bfOffBits] ' get base of image in file (skip header) + pixColorAddr := @byte[fileBitsBase][nOffset] ' add in offset to 24-bit color + + if showDebug + debug("- FileOffset=", udec_(nOffset), ", RC=(", udec_(nRow), ",", udec_(nColumn), ", ofst=", uhex_long_(pixColorAddr), ", base=", uhex_long_(fileBitsBase), ")") + +PRI isDebugLocn(nRow, nCol) : status + status := FALSE + return + 'if (nRow == 31 && nCol < 4) || (nRow < 2 && nCol < 3) || (nRow == 31 && nCol > 61) || (nRow < 2 && nCol > 61) + ' status := TRUE ' FALSE ' turn off debug + +DAT { .bmp fiile work area } + + +fileHeaderMsg byte "File Header",0 +fileStartMsg byte "FileImage start",0 +fileEndMsg byte "FileImage end",0 +screenMessage byte "screenBuffer",0 +screenRed byte "screenRedBuffer",0 +screenBlue byte "screenGreenBuffer",0 +screenGreen byte "screenBlueBuffer",0 + + ALIGNL + byte 0 ' fill aligning header to avoid gaps + byte 0 +BMPHeader 'Mostly using info from here: http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html +bfType byte "B","M" +bfSize long 0 +bfReserved1 word 0 +bfReserved2 word 0 +bfOffBits long 54 +biSize long 40 +biWidth long 0 +biHeight long 10 +biPlanes word 1 +biBitCount word 24 +biCompression long 0 +biSizeImage long 0 + +biXPelsPerMeter long 0 +biYPelsPerMeter long 0 + +biClrUsed long 0 +biClrImportant long 0 + +CON { license } + +{{ + + + ------------------------------------------------------------------------------------------------- + MIT License + + Copyright (c) 2020 Iron Sheep Productions, LLC + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + ================================================================================================= + +}} diff --git a/driver/isp_hub75_hwGeometry.spin2 b/driver/isp_hub75_hwGeometry.spin2 index 9568f06..ca858cc 100644 --- a/driver/isp_hub75_hwGeometry.spin2 +++ b/driver/isp_hub75_hwGeometry.spin2 @@ -38,19 +38,7 @@ CON { Hardware Description } ' ================================================================================================= -' (2) Describe your desired effective color resolution (8-24 bit) more bits, more ram need! -' ================================================================================================= -' number of pwm bits is number of PWM frames the driver needs to allocate -' each PWM frame is (DISPLAY PIXEL COUNT / 2) bytes in size -' -' NOTE: we use 2 full PWM frame-sets so we can double buffer the screen generation - -' NOTE: 16 or 20 seem useful without going crazy with ram usage -' - MAX_PWM_WIDTH_IN_BITS = 16 ' use 8, 12, 16, 20, 23 or 24 NOTE: each bump uses more memory! - -' ================================================================================================= -' (3) Describe the overall layout of your hardware panels: +' (2) Describe the overall layout of your hardware panels: ' ================================================================================================= ' ' AUTHORs 1st configuration diff --git a/driver/isp_hub75_panel.spin2 b/driver/isp_hub75_panel.spin2 index 4b412ee..db89689 100644 --- a/driver/isp_hub75_panel.spin2 +++ b/driver/isp_hub75_panel.spin2 @@ -7,9 +7,9 @@ '' -- see below for terms of use '' E-mail..... stephen@ironsheep.biz '' Started.... Oct 2020 -'' Updated.... 17 Oct 2020 +'' Updated.... 01 Dec 2020 '' -'' This object offers both .bmp file loading support as well as screen buffer 24bit loading support +'' This object provides 24bit screen buffer to PWM buffers support '' ================================================================================================= @@ -30,20 +30,6 @@ DAT { pre-initialized } didShow byte FALSE didShowCount byte 2 ' just the first two screens -' TEMP while figuring out code -pwm12Bit - word $0fff, $07ff, $03ff, $01ff - word $00ff, $007f, $003f, $001f - word $000f, $0007, $0003, $0001 - word 0 - -pwm16Bit - word $ffff, $7fff, $3fff, $1fff - word $0fff, $07ff, $03ff, $01ff - word $00ff, $007f, $003f, $001f - word $000f, $0007, $0003, $0001 - word $0000 - VAR long cog @@ -65,7 +51,7 @@ CON { RAM/FLASH } ' ---------------------------------------------------------- -PUB start() : ok +PUB start() : ok '' Start the backend pasm2 driver for the matrix debug("- PANEL: Start Matrix COG") @@ -93,7 +79,7 @@ PUB fillPanel(threeBitColor) '' Fill screen but without PWM (for testing underlying driver) matrix.fillPanel(threeBitColor) -PUB loadScreen(p24bitScreen) | redByte, greenByte, blueByte, pPwmFrame, pPwmFrameSet, panelCol, panelRow, p24bitColor, colorValue, colorMask, bitCount, bitNumber, panelBGR, tmpVarA, tmpVarB +PUB convertScreen2PWM(p24bitScreen) | redByte, greenByte, blueByte, pPwmFrame, pPwmFrameSet, panelCol, panelRow, p24bitColor, colorValue, colorMask, bitCount, bitNumber, panelBGR, tmpVarA, tmpVarB '' Load a 24-bit image into PWM frame buffers ' XYZZYpnl debug("- PANEL: loading screen at @", uhex_long_(p24bitScreen)) @@ -123,7 +109,7 @@ nextColumn ' 'nOffset := ((rowIndex * screen.MAX_PANEL_COLUMNS) + columnIndex) * screen.DISPLAY_BYTES_PER_COLOR 'pixColorAddr := @byte[pScreenInMemory][nOffset] ' add in offset to 24-bit color - mov p24bitColor, panelRow + mov p24bitColor, panelRow sub p24bitColor, #1 ' get rowIndex - 1 [32-1] -> [31-0] mul p24bitColor, #screen.MAX_DISPLAY_COLUMNS ' x maxColumns add p24bitColor, panelCol ' + columnIndex @@ -131,7 +117,7 @@ nextColumn mul p24bitColor, #screen.DISPLAY_BYTES_PER_COLOR ' * bytes / 24-bit color add p24bitColor, p24bitScreen ' + base address of screen rdlong colorValue, p24bitColor - ' red := byte[p24bitScreen][p24bitColor][0] + ' red := byte[p24bitScreen][p24bitColor][0] GETBYTE tmpVarA, colorValue,#0 call #cvtTmpA2pwm mov redByte, tmpVarA @@ -149,18 +135,18 @@ nextColumn ' write color information to our PWM buffers ' expand 24-bit pixel into 8 pwm frames of 3-bit pixel ' for ea. bit do... - mov bitCount, #screen.MAX_PWM_FRAMES ' MAX_PWM_WIDTH_IN_BITS bits to scan in LONG - mov bitNumber, #0 ' start with bit0 of [0-MAX_PWM_WIDTH_IN_BITS - 1] + mov bitCount, #screen.MAX_PWM_FRAMES ' MAX PWM FRAME bits to scan in LONG + mov bitNumber, #0 ' start with bit0 of [0-MAX_PWM_FRAMES - 1] nextBit ' calculate offset to frame for this bit # ' frameIdx := 0 #> nBitNumber <# screen.MAX_PWM_FRAMES - 1 ' MAX 8 pwm frames so limit our index ' nFrameOffset := frameIdx * screen.MAX_PWM_FRAME_SIZE_IN_LONGS ' 256 longs in each frame ' pPwmFrame := @long[getActivePwmBuffer()][nFrameOffset] mov pPwmFrame, bitNumber - mul pPwmFrame, ##screen.MAX_PWM_FRAME_SIZE_IN_BYTES + mul pPwmFrame, ##screen.MAX_PWM_FRAME_SIZE_IN_BYTES ' calculate pointer to frame for thic bit # add pPwmFrame, pPwmFrameSet - ' build RGB1 or RGB2 bits to be stored in panel word + ' build RGB1 or RGB2 bits to be stored in panel word ' rBit := red & (1 << bitNumber) > 0 ? 1 : 0 ' gBit := green & (1 << bitNumber) > 0 ? 1 : 0 ' bBit := blue & (1 << bitNumber) > 0 ? 1 : 0 @@ -177,7 +163,7 @@ nextBit cmp tmpVarA, #16 wc ' loading top or bottom half of screen? if_c mov tmpVarB, #0 ' NO, is RGB1 (top) if_nc mov tmpVarB, #1 ' YES, is RGB2 (bottom) - ' convert row number to row number of top-half of panel + ' convert row number to row number of top-half of panel if_nc sub tmpVarA, #16 ' 0-31 -> 0-15 ' is top-RGB1 or bottom-RGB2 color? ' if tmpVarB @@ -219,7 +205,7 @@ cvtTmpA2pwm cmp tmpVarA, #255 wz ' special case: if $ff return all 1 bits if_z not tmpVarB, tmpVarB if_z jmp #noShift - sub tmpVarA, #1 + sub tmpVarA, #1 bmask tmpVarB, tmpVarA ' successively move CY into lower bits mov tmpVarA, tmpVarB ' return our new value noShift @@ -240,61 +226,11 @@ PRI dumpFrameSet(pPwmFrameSet) | pFrameBuffer, frameIndex repeat frameIndex from 0 to 7 pFrameBuffer := @long [pPwmFrameSet][frameIndex * screen.MAX_PWM_FRAME_SIZE_IN_LONGS] dumpFrame(pFrameBuffer) - + PRI dumpFrame(pFrameBuffer) dbgMemDump(@frameMessage, pFrameBuffer, 32) - -PUB loadBitmap(pBitmapFile) | nPanelCol, nPanelRow, blue, green, red, haveError, showDebug, bInvalidFileStatus, pPwmFrameSet - '' Load a 24-bit .bmp file image into screen buffer - ' HEADS UP!!! - ' this is currently limited to "single panel size" untill we rerite this code - - ' save address of 24bit file image for use by called routines - pBitmapFileInMemory := pBitmapFile - - ' XYZZYpnl debug("- Study BMP") - bInvalidFileStatus := validateBmpFile(pBitmapFile) - if bInvalidFileStatus == FALSE - ' TODO: how do we warn of this? - abort - - ' clear buffer - pPwmFrameSet := clearPwmFrameBuffer() ' clear PWM frames and get pointer to buffer - - ' fill buffer - repeat nPanelRow from 0 to screen.MAX_PANEL_ROWS - 1 - repeat nPanelCol from 0 to screen.MAX_PANEL_COLUMNS - 1 - 'debug("loadBitmap() - RC=(", udec_(nPanelRow), ", ", udec_(nPanelCol), ")") - haveError := FALSE - if(nPanelRow > screen.MAX_PANEL_ROWS - 1) - ' XYZZYpnl debug("- ERROR bad nPanelRow value [", udec_(nPanelRow), " > ", udec_(screen.MAX_PANEL_ROWS - 1), "]") - haveError := TRUE - - if(nPanelCol > screen.MAX_PANEL_COLUMNS - 1) - ' XYZZYpnl debug("- ERROR bad nPanelCol value [", udec_(nPanelCol), " > ", udec_(screen.MAX_PANEL_COLUMNS - 1), "]") - haveError := TRUE - - if haveError == FALSE - showDebug := FALSE - if isDebugLocn(nPanelRow, nPanelCol) - showDebug := TRUE ' FALSE ' turn off debug - - red, green, blue := get24BitBMPColorForRC(nPanelRow, nPanelCol) - - if showDebug - ' XYZZYpnl debug(" - RC=(", udec_(nPanelRow), ", ", udec_(nPanelCol), "), RGB=(", uhex_(red), uhex_(green), uhex_(blue), ")") - - setPixelForRC_OLD(nPanelRow, nPanelCol, RGB(red, green, blue)) - - -PRI RGB(red, green, blue) : r, g, b - 'Blue byte first because that's how stored in bitmap... - r := color.correctedSingleColor(color.LED_RED, red) - g := color.correctedSingleColor(color.LED_GREEN, green) - b := color.correctedSingleColor(color.LED_BLUE, blue) - -PRI clearPwmFrameBuffer() : pPwmFrameSet +PRI clearPwmFrameBuffer() : pPwmFrameSet ' clear entire PWM buffer ' implement double buffering by alternating between our two pwm-frame-sets usePwmFrameset1 := !usePwmFrameset1 @@ -312,68 +248,13 @@ PRI getPwmFrameAddressForBit(nBitNumber) : pFrameBuffer | nFrameOffset, frameIdx pFrameBuffer := @long[getActivePwmBuffer()][nFrameOffset] 'debug("- PWM frame(", udec_(frameIdx), "), ", uhex_long(pFrameBuffer)) - -PRI setPixelForRC_OLD(nPanelRow, nPanelCol, red, green, blue) | rBit, gBit, bBit, pPwmFrame, bitNumber, rPwmBits, gPwmBits, bPwmBits - ' for each 24bit color write to PWM frames - ' ' XYZZYpnl debug("setPixel() - x,y=(", udec_(nPanelCol), ", ", udec_(nPanelRow), ")") - rPwmBits := dutyCycleForIntensity(red) - gPwmBits := dutyCycleForIntensity(green) - bPwmBits := dutyCycleForIntensity(blue) - ' expand 24-bit pixel into 8 pwm frames of 3-bit pixel - repeat bitNumber from screen.MAX_PWM_FRAMES - 1 to 0 - pPwmFrame := getPwmFrameAddressForBit(bitNumber) - rBit := rPwmBits & (1 << bitNumber) > 0 ? 1 : 0 - gBit := gPwmBits & (1 << bitNumber) > 0 ? 1 : 0 - bBit := bPwmBits & (1 << bitNumber) > 0 ? 1 : 0 - setPanelColorBitsForRC(pPwmFrame, nPanelRow, nPanelCol, rBit, gBit, bBit) - -PRI dutyCycleForIntensity(hex8bit) : pwmBits - ' CALCULATE: proper duty cycle for intensity of 0-255 - { --- VERSION 1 - Bits spread throughout --- - if hex8bit >= 145 - ' upper half - if hex8bit >= 218 - ' upper half - pwmBits := (hex8bit == 255) ? $ff : $7f - else - ' lower half - pwmBits := (hex8bit >= 181) ? $77: $37 - else - ' lower half - if hex8bit > 73 - ' upper half - pwmBits := (hex8bit >= 109) ? $33 : $31 - else - ' lower half - pwmBits := (hex8bit == 0) ? $00 : (hex8bit >= 36) ? $11 : $01 - '} - '{ --- VERSION 2 - Bits grounded to right --- - if hex8bit >= 145 - ' upper half - if hex8bit >= 218 - ' upper half - pwmBits := (hex8bit == 255) ? $ff : $7f - else - ' lower half - pwmBits := (hex8bit >= 181) ? $3f: $1f - else - ' lower half - if hex8bit > 73 - ' upper half - pwmBits := (hex8bit > 109) ? $0F : $07 - else - ' lower half - pwmBits := (hex8bit == 0) ? $00 : (hex8bit >= 36) ? $03 : $01 - '} - VAR { buffer addresses } long pBitmapFileInMemory long pScreenInMemory PRI setPanelColorBitsForRC(pPwmFrame, nPanelRow, nPanelCol, rBit, gBit, bBit) | nBffrR, nBffrC, isRGB2, byteIdx, maskBitsBGR, bitsBGR, currByte, showDebug - ' write color bits to a PWM frame at frame[r][c] - ' FIXME: UNDONE PANEL GEOM ASSUMPTION + ' write color bits to a PWM frame at frame[r][c] nBffrR := 0 #> nPanelRow <# screen.MAX_DISPLAY_ROWS - 1 nBffrC := 0 #> nPanelCol <# screen.MAX_DISPLAY_COLUMNS - 1 isRGB2 := (nBffrR > 15) ? TRUE : FALSE @@ -391,126 +272,16 @@ PRI setPanelColorBitsForRC(pPwmFrame, nPanelRow, nPanelCol, rBit, gBit, bBit) | currByte := byte[pPwmFrame][byteIdx] & !maskBitsBGR if byteIdx > 1023 debug("ERROR! byte index calc failure have=(" , udec_(byteIdx), ") of [0-1023]") - else - byte[pPwmFrame][byteIdx] := currByte | bitsBGR - - -PRI validateBmpFile(pBffr) : bValidStatus | p, i, iStart, iEnd, pLastByte - ' interpret .BMP header and return pointer to image - - ' XYZZYpnl debug("- Studying in-memory file") - bValidStatus := TRUE - 'analyze bitmap image - p:=pBffr - bytemove(@bfType,p,2) 'read bmp header - p+=2 - bytemove(@bfSize,p,4) 'read bmp header - p+=4 - bytemove(@bfReserved1,p,4) 'read bmp header - p+=4 - bytemove(@bfOffBits,p,16) 'read bmp header - p+=16 - bytemove(@biPlanes,p,4) - p+=4 - bytemove(@biCompression,p,24) - p+=24 - - 'calculate actual bytes in palette - i := bfOffBits-54 - p += i - - iStart := pBffr + bfOffBits - iEnd := iStart + biSizeImage - 1 - - ' return pointer to last byte in bitmap - pLastByte := p + (biHeight * biWidth * 3) - 1 - - ' XYZZYpnl debug("BitMap file @0x", uhex_(pBffr)) - ' XYZZYpnl debug(" - size=", udec_(bfSize)) - ' XYZZYpnl debug(" - OffsetBits=", udec_(bfOffBits)) - 'debug(" - #planes=", udec_(biPlanes)) - ' XYZZYpnl debug(" - w,h=", udec_(biWidth), ",", udec_(biHeight)) - ' XYZZYpnl debug(" - szImage=", udec_(biSizeImage)) - 'debug(" - compression=", udec_(biCompression)) - ' XYZZYpnl debug(" - bitCount=", udec_(biBitCount)) - ' XYZZYpnl debug(" - end @0x", uhex_(pLastByte)) - - ' XYZZYpnl debug(" - Img-start @0x", uhex_(iStart)) - ' XYZZYpnl debug(" - Img-end @0x", uhex_(iEnd)) - - if biWidth <> 64 or biHeight <> 32 - ' XYZZYpnl debug(" !! invalid BMP size! [NOT 64x32]") - bValidStatus := FALSE - - if byte[@bfType][0] <> $42 || byte[@bfType][1] <> $4d ' B, M - ' XYZZYpnl debug(" !! invalid BMP file type! [NOT 'BM']") - bValidStatus := FALSE - - if biCompression <> 0 - ' XYZZYpnl debug(" !! invalid BMP compression! [is compressed]") - bValidStatus := FALSE - - if bValidStatus == FALSE - ' XYZZYpnl debug("- ERROR invalid BMP!") else - ' XYZZYpnl debug("-good BMP size! [64x32]") + byte[pPwmFrame][byteIdx] := currByte | bitsBGR - 'dbgMemDump(@fileHeaderMsg, pBffr, bfOffBits) - 'dbgMemDump(@fileStartMsg, iStart, 32) - 'dbgMemDump(@fileEndMsg, iEnd-32-1, 32) - PRI isDebugLocn(nRow, nCol) : status status := FALSE return if (nRow == 31 && nCol < 4) || (nRow < 2 && nCol < 3) || (nRow == 31 && nCol > 61) || (nRow < 2 && nCol > 61) status := TRUE ' FALSE ' turn off debug -PRI getPixelAddressForBMPRowColumn(nRow, nColumn) : pixColorAddr | rowIndex, columnIndex, nOffset, fileBitsBase, showDebug - ' Row is inverted in .BMP file... - rowIndex := (screen.MAX_PANEL_ROWS - 1) - nRow - - ' Column is normal in file... - columnIndex := nColumn - - showDebug := FALSE - 'if (bitIdx == 0 || bitIdx == 31) && nBffrR < 2 - if isDebugLocn(nRow, nColumn) - 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 - - fileBitsBase := @byte[pBitmapFileInMemory][bfOffBits] ' get base of image in file (skip header) - pixColorAddr := @byte[fileBitsBase][nOffset] ' add in offset to 24-bit color - - if showDebug - ' XYZZYpnl debug("- FileOffset=", udec_(nOffset), ", RC=(", udec_(nRow), ",", udec_(nColumn), ", ofst=", uhex_long_(pixColorAddr), ", base=", uhex_long_(fileBitsBase), ")") - - -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(nColumn > screen.MAX_PANEL_COLUMNS - 1) - debug("- ERROR bad nColumn value [", udec_(nColumn), " > ", udec_(screen.MAX_PANEL_COLUMNS - 1), "]") - - pixColorAddr := getPixelAddressForBMPRowColumn(nRow, nColumn) - ' our intername .bmp file byte order is BGR! - blue := byte[pixColorAddr][0] - green := byte[pixColorAddr][1] - red := byte[pixColorAddr][2] - - -PRI dumpTwinRows() - ' XYZZYpnl debug("`temp ' Red TL,R ", uhex_long_(long[@singleBuffer][0]), ", ", uhex_long_(long[@singleBuffer][1]), " ' 13") - ' XYZZYpnl debug("`temp ' Red BL,R ", uhex_long_(long[@singleBuffer][62]), ", ", uhex_long_(long[@singleBuffer][63]), " ' 13") - ' XYZZYpnl debug("`temp ' Grn TL,R ", uhex_long_(long[@singleBuffer][64]), ", ", uhex_long_(long[@singleBuffer][65]), " ' 13") - ' XYZZYpnl debug("`temp ' Grn BL,R ", uhex_long_(long[@singleBuffer][126]), ", ", uhex_long_(long[@singleBuffer][127]), " ' 13") - ' XYZZYpnl debug("`temp ' Blu TL,R ", uhex_long_(long[@singleBuffer][128]), ", ", uhex_long_(long[@singleBuffer][129]), " ' 13") - ' XYZZYpnl debug("`temp ' Blu BL,R ", uhex_long_(long[@singleBuffer][190]), ", ", uhex_long_(long[@singleBuffer][191]), " ' 13") - - PUB dbgMemDump(bfrId, buffer, len) | bytBffr, colIdx, rowIdx, maxCol, maxRow, dispLen '' Dump bytes in hex format to debug() terminal debug("`temp 13 '", zstr_(bfrId), ": bffr=", uhex_long_(buffer), "(", udec_(len), ")' 13") @@ -539,50 +310,17 @@ PUB dbgMemDump(bfrId, buffer, len) | bytBffr, colIdx, rowIdx, maxCol, maxRow, di bytBffr += 16 debug("`temp 13") ' newline - waitus(85) ' 50 too short, 70 less issue, 75 better, + waitus(85) ' 50 too short, 70 less issue, 75 better, waitms(2) DAT { .bmp fiile work area } - - testValue long $87654321 testValueMsg byte "Test value",0 frameMessage byte "FrameBuffer",0 -fileHeaderMsg byte "File Header",0 -fileStartMsg byte "FileImage start",0 -fileEndMsg byte "FileImage end",0 -screenMessage byte "screenBuffer",0 -screenRed byte "screenRedBuffer",0 -screenBlue byte "screenGreenBuffer",0 -screenGreen byte "screenBlueBuffer",0 - - ALIGNL - byte 0 ' fill aligning header to avoid gaps - byte 0 -BMPHeader 'Mostly using info from here: http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html -bfType byte "B","M" -bfSize long 0 -bfReserved1 word 0 -bfReserved2 word 0 -bfOffBits long 54 -biSize long 40 -biWidth long 0 -biHeight long 10 -biPlanes word 1 -biBitCount word 24 -biCompression long 0 -biSizeImage long 0 - -biXPelsPerMeter long 0 -biYPelsPerMeter long 0 - -biClrUsed long 0 -biClrImportant long 0 - - + CON { license } {{ @@ -611,6 +349,5 @@ CON { license } OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================================= - -}} +}} diff --git a/driver/isp_hub75_rgb3bit.spin2 b/driver/isp_hub75_rgb3bit.spin2 index 3b2cedd..2b34efe 100644 --- a/driver/isp_hub75_rgb3bit.spin2 +++ b/driver/isp_hub75_rgb3bit.spin2 @@ -104,7 +104,7 @@ VAR ' write values here to pass to driver long dvrCommand - long dvrArgument + long dvrArgument long cog @@ -136,7 +136,7 @@ PUB start() : ok | bSetLowPins overlappedLatch := TRUE setupPins() resetPanel() - else + else debug("- have OTHER") overlappedLatch := FALSE @@ -270,7 +270,7 @@ PRI dbgMemDump(bfrId, buffer, len) | bytBffr, colIdx, rowIdx, maxCol, maxRow, di bytBffr += 16 debug("`temp 13") ' newline - waitus(85) ' 50 too short, 70 less issue, 75 better, + waitus(85) ' 50 too short, 70 less issue, 75 better, waitms(1) ' -------------------------------------------------------------------------------------------------- @@ -403,7 +403,7 @@ drive_matrix if_z setd outInst1of3, #OUTB if_z setd outInst2of3, #OUTB if_z setd outInst3of3, #OUTB - + ' init row address mov row_addr, addrValue15 ' reset address to 15 [A-D addr all ones] @@ -419,14 +419,14 @@ getCommand rdlong nxtCommand, pCommmand rdlong nxtArgument, pArgument cmp nxtCommand, #CMD_DONE wz - if_z jmp #chksDone ' redraw current buffer + if_z jmp #chksDone ' redraw current buffer 'debug("* cmd=", udec_(nxtCommand), ", arg=", uhex_long_(nxtArgument)) chkShow cmp nxtCommand, #CMD_SHOW_BUFFER wz if_nz jmp #chkShowPwm call #loadBuffer 'debug(" - load done") - jmp #markCmdComplete ' redraw current buffer + jmp #markCmdComplete ' redraw current buffer chkShowPwm cmp nxtCommand, #CMD_SHOW_PWM_BUFFER wz if_nz jmp #chkFill @@ -435,7 +435,7 @@ chkShowPwm jmp #getCommand ' check for next command (or same still there) chkFill cmp nxtCommand, #CMD_FILL_COLOR wz - if_nz jmp #chksDone ' redraw current buffer + if_nz jmp #chksDone ' redraw current buffer call #fillBuffer 'debug(" - fill done") jmp #markCmdComplete ' redraw current buffer @@ -510,7 +510,7 @@ dumpTwinRows chksDone cmp nxtCommand, #CMD_DONE wz - if_z jmp #wrCurrent ' redraw current buffer + if_z jmp #wrCurrent ' redraw current buffer 'debug("--> *ERROR* Unknown cmd(", udec_(nxtCommand), ") arg=", uhex_long_(nxtArgument)) markCmdComplete 'debug(" - unknown cmd done") @@ -609,10 +609,10 @@ outInst2of3 MUXQ OUTA, reg_value ' write contents of LS-b djnz byt_ctr, #clkNONextByte add reg_offset, #1 djnz reg_ctr, #clkNONextReg - + ' let's latch drvh #MTX_LED_PIN_OE - ' write address + ' write address add row_addr, addrValue1 ' incr address by 1 call #emitAddr @@ -653,7 +653,7 @@ isr2 isr3 nop reti3 - + 'DAT { data } @@ -701,12 +701,12 @@ nxtArgument res 1 pwmBffrStart res 1 pwmFrameCt res 1 -fillBffr res 1 ' ptr to single PWM frame sized buffer buffer -- long: where bits of each byte are 'x x B2 G2 R2 G1 B1 R1' +fillBffr res 1 ' ptr to single PWM frame sized buffer buffer -- long: where bits of each byte are 'x x B2 G2 R2 G1 B1 R1' fillLong res 1 ' value to write to each long fillCount res 1 ' remaining count of bytes to write fillOffset res 1 ' offset into fillBffr -reg_offset res 1 +reg_offset res 1 reg_value res 1 byt_ctr res 1 dbgBffr res 1 @@ -720,7 +720,7 @@ reg_ctr res 1 FIT 496 - + CON { license } {{ @@ -749,5 +749,5 @@ CON { license } OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================================= - + }} diff --git a/driver/isp_hub75_screenAccess.spin2 b/driver/isp_hub75_screenAccess.spin2 index d50143e..1a8db56 100644 --- a/driver/isp_hub75_screenAccess.spin2 +++ b/driver/isp_hub75_screenAccess.spin2 @@ -49,15 +49,14 @@ CON { reinterpret the users selections for driver internal use } MAX_PWM_FRAME_SIZE_IN_BYTES = ((MAX_PHYSICAL_COLUMNS * MAX_PHYSICAL_ROWS) / 2) MAX_PWM_FRAME_SIZE_IN_LONGS = MAX_PWM_FRAME_SIZE_IN_BYTES / 4 - ' how many PWM frames does our user want to use? - MAX_PWM_FRAMES = user.MAX_PWM_WIDTH_IN_BITS ' user desired color depth + ' how many PWM frames does our DRIVER use? + MAX_PWM_FRAMES = 16 ' compiled color depth -' DISPLAY_BITS_PER_COLOR = 24 PANEL_BITS_PER_COLOR = 3 ' (8 bits per byte) - DISPLAY_BYTES_PER_COLOR = DISPLAY_BITS_PER_COLOR / 8 + DISPLAY_BYTES_PER_COLOR = DISPLAY_BITS_PER_COLOR / 8 ' (rounded up to fill a full long - leaves 0-3 bytes unused at end) DISPLAY_SIZE_IN_BYTES = (((MAX_DISPLAY_COLUMNS * MAX_DISPLAY_ROWS * DISPLAY_BYTES_PER_COLOR) + 3) / 4) * 4 @@ -81,7 +80,7 @@ PUB setScreen(pScreen) 'debug("7s:setScreen") pExtScreen := pScreen -PUB screenAddress() : pScreen +PUB screenAddress() : pScreen '' Return the address of the external screen buffer pScreen := pExtScreen @@ -113,7 +112,7 @@ PUB dbgMemDump(bfrId, buffer, len) | bytBffr, colIdx, rowIdx, maxCol, maxRow, di bytBffr += 16 debug("`temp 13") ' newline - waitus(85) ' 50 too short, 70 less issue, 75 better, + waitus(85) ' 50 too short, 70 less issue, 75 better, waitms(2) @@ -147,4 +146,3 @@ CON { license } SOFTWARE. ================================================================================================= }} - diff --git a/driver/isp_hub75_screenUtils.spin2 b/driver/isp_hub75_screenUtils.spin2 index 6002a87..289973a 100644 --- a/driver/isp_hub75_screenUtils.spin2 +++ b/driver/isp_hub75_screenUtils.spin2 @@ -12,7 +12,7 @@ '' ================================================================================================= CON { Object Interface: PUBLIC ENUMs } - + OBJ { Objects Used by this Object } @@ -78,4 +78,3 @@ CON { license } SOFTWARE. ================================================================================================= }} - diff --git a/driver/isp_hub75_scrollingText.spin2 b/driver/isp_hub75_scrollingText.spin2 index 44a4a46..8496a86 100644 --- a/driver/isp_hub75_scrollingText.spin2 +++ b/driver/isp_hub75_scrollingText.spin2 @@ -130,7 +130,7 @@ PUB scrollText(loopMode) | bValidRequest if loopMode == SCROLL_ONCE_TO_CLEAR remainingPixToScroll := (ctCharsToScroll * (charWidthInPix + horizontalGapInPix)) ' bug 3 chars short font8A - else + else remainingPixToScroll := ((ctCharsToScroll * (charWidthInPix + horizontalGapInPix)) - horizontalGapInPix) - windowWidthInPix ' bug 1 char short font 8A debug("stx:scrlTxt() ", udec(instanceID), ", ", udec(remainingPixToScroll), udec(ctCharsToScroll), udec(maxVisibleChars), udec(charWidthInPix), udec(horizontalGapInPix)) @@ -150,7 +150,7 @@ PUB scrollTextAtRCOfColor(row, column, widthInChars, pZString, direction, rgbCol remainingPixToScroll := ((ctCharsToScroll * (charWidthInPix + horizontalGapInPix)) - horizontalGapInPix) - windowWidthInPix ' if our string is shorter than our window then right is string-end, else right is window-end nextToAppearIndex := min(maxVisibleChars, ctCharsToScroll) - + debug("- scrollTxAtRCOfClr() ", udec(instanceID), ", RC=(", udec_(row), udec_(column), "), ", zstr(pZString), ", CT=", udec_(ctCharsToScroll), ", VIS=", udec_(maxVisibleChars), ", NTAI=", udec_(nextToAppearIndex)) if ctCharsToScroll > 0 bytemove(@scrollChars, pZString, ctCharsToScroll) @@ -178,7 +178,7 @@ PUB scrollTextAtRCOfColor(row, column, widthInChars, pZString, direction, rgbCol if direction == DIR_TO_LEFT placeCharsAtRCWithColor(topRow, leftColumn, charPixOffset, windowWidthInPix, firstVisCharIndex, scrollTextColor) charPixOffset++ ' we showed first window content just now - else + else placeCharsAtRCWithColor(topRow, leftColumn, charPixOffset, windowWidthInPix, firstVisCharIndex, scrollTextColor) charPixOffset-- ' we showed first window content just now if charPixOffset < 0 @@ -189,10 +189,10 @@ PUB scrollTextAtRCOfColor(row, column, widthInChars, pZString, direction, rgbCol debug("stx:scrollTxAtRCOfClr() - NOT IDLE!") -PUB animateScroll() +PUB animateScroll() '' Do one scroll step, if one is pending if not isScrollingComplete() - 'startTime := getct() + 'startTime := getct() 'debug("stx:AS()") ' if scrolling left then head is next loosing left most pixel (offset dictates) ' and tail if moving left most pixel onscreen @@ -212,7 +212,7 @@ PUB animateScroll() firstVisCharIndex++ if firstVisCharIndex > ctCharsToScroll - 1 && scrollMode <> SCROLL_ONCE_TO_CLEAR firstVisCharIndex := 0 - else + else placeCharsAtRCWithColor(topRow, leftColumn, charPixOffset, windowWidthInPix, firstVisCharIndex, scrollTextColor) charPixOffset-- ' we showed one just now ' if finished scrolling first char offscreen then reset to show head of next char @@ -301,12 +301,12 @@ PRI placeSpaceAtRC(row, column, widthInPix) : endColumn | colIndex, rowIndex PRI placeBitmapFrontAtRCWithColor(row, column, bitInset, nbrFieldBits, pCharBitmap, rgbColor) : endColumn | cBitIdx, cByteIdx, cRowBits, pixColor, colOffset, pixColumn, pixRow, cBitOffset, nbrCharBits - ' Write cChar to display R,C using rgbColor using given bitmap - 'startTime := getct() + ' Write cChar to display R,C using rgbColor using given bitmap + 'startTime := getct() nbrCharBits := (nbrFieldBits > 0) ? nbrFieldBits - horizontalGapInPix : 0 'debug("stx:pbF ", udec(column), udec(bitInset), udec(nbrFieldBits), udec(nbrCharBits), uhex_long(pCharBitmap)) ' if we have some but not all char bits then we are leading char - 'if nbrCharBits <> charWidthInPix ' TESTING + 'if nbrCharBits <> charWidthInPix ' TESTING ' rgbColor := $00ff00 ' TESTING color our leading char green endColumn := column + nbrCharBits ' point to gap locn if nbrCharBits > 0 @@ -333,8 +333,8 @@ PRI placeBitmapFrontAtRCWithColor(row, column, bitInset, nbrFieldBits, pCharBitm PRI placeBitmapBackAtRCWithColor(row, column, bitInset, nbrCharBits, pCharBitmap, rgbColor) : endColumn | cBitIdx, cByteIdx, cRowBits, pixColor, colOffset, pixColumn, pixRow, cBitOffset - ' Write cChar to display R,C using rgbColor using given bitmap - 'startTime := getct() + ' Write cChar to display R,C using rgbColor using given bitmap + 'startTime := getct() 'debug("stx:pbB ", udec(column), udec(bitInset), udec(nbrCharBits), uhex_long(pCharBitmap)) 'rgbColor := $ffff00 ' TESTING color our trailing char yellow endColumn := column + nbrCharBits @@ -390,4 +390,3 @@ CON { license } SOFTWARE. ================================================================================================= }} - diff --git a/driver/isp_hub75_segment.spin2 b/driver/isp_hub75_segment.spin2 index b683ba4..899f3e9 100644 --- a/driver/isp_hub75_segment.spin2 +++ b/driver/isp_hub75_segment.spin2 @@ -11,18 +11,18 @@ '' '' ================================================================================================= -' There are two types of segments +' There are two types of segments ' one of which is rotated 3 times to get 4 shapes ' the other is the middle segment ' The mechanical segments slide on and back off of screen ' the background is generally black ' -' A +' A ' F B -' G +' G ' E C -' D +' D CON { segment states, names, orientations and such } @@ -35,7 +35,7 @@ SEG_LENGTH = 10 cBlack = $000000 -OBJ +OBJ screen : "isp_hub75_screenAccess" pixels : "isp_hub75_screenUtils" color : "isp_hub75_color" @@ -73,7 +73,7 @@ PUB placeSegment(row, column, orientation, initialState, rgbColor) segWidth := 3 OTHER: debug("SEG: BAD segment type!") - abort + abort ' if the segment is initially showing, let's draw it! if initialState <> currentState updateSegmentToState(initialState) @@ -95,12 +95,12 @@ PUB isMovementComplete() : status '' Return T/F where T means that all movement for this segment is complete status := (desiredEndState == currentState) -PUB animateStep() +PUB animateStep() '' Do one animation step, if one is pending if not isMovementComplete() updateSegmentToState(nextState) -PUB moveSegmentToState(newEndState) +PUB moveSegmentToState(newEndState) '' Start sequence of segment updates to desired state (on/off) 'debug("seg:id(segT", udec_(segOrientation), "), moveTo (st", udec_(desiredEndState), ") -> (st", udec_(newEndState), ")") ' if we are asking to be in a different state then... @@ -111,7 +111,7 @@ PUB moveSegmentToState(newEndState) abort if newEndState <> STATE_OFF && newEndState <> STATE_ON debug("SEG: BAD end-state must be ON or OFF!") - abort + abort if newEndState == STATE_ON nextState := STATE_3RD_ON else @@ -162,7 +162,7 @@ PRI updateVerticalSegment(newState) | pixInset, columnIndex pixInset := 0 repeat columnIndex from 0 to SEG_WIDTH - 1 drawLine(segStartY + pixInset, segStartX + columnIndex, segStartY + SEG_LENGTH - 1 - pixInset, segStartX + columnIndex, segRgbColor) - pixInset++ + pixInset++ STATE_3RD_OFF: ' smallest 2 lines showing drawLine(segStartY + 0, segStartX + 0, segStartY + SEG_LENGTH - 1 - 0, segStartX + 0, segRgbColor) ' mid drawLine(segStartY + 1, segStartX + 1, segStartY + SEG_LENGTH - 1 - 1, segStartX + 1, segRgbColor) ' shortest @@ -310,11 +310,11 @@ PRI drawLine(fmRow, fmColumn, toRow, toColumn, rgbColor) | row, column toColumn := 0 #> toColumn <# screen.MAX_DISPLAY_COLUMNS - 1 if fmRow == toRow ' draw Horizontal Line - repeat column from fmColumn to toColumn + repeat column from fmColumn to toColumn pixels.drawPixelAtRCwithRGB(fmRow, column, color.rgbForCValue(rgbColor)) elseif fmColumn == toColumn ' draw Vertical Line - repeat row from fmRow to toRow + repeat row from fmRow to toRow pixels.drawPixelAtRCwithRGB(row, fmColumn, color.rgbForCValue(rgbColor)) else debug("DIAG lines not implemented !") @@ -357,6 +357,5 @@ CON { license } OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================================================= - -}} +}}