RGB332 PWM Color for Hub75

master
wolfgang 2 years ago
parent 01de59f1b9
commit bf59543d10
  1. 67
      hub75sender.py

@ -7,7 +7,39 @@ import math
from migen import *
from migen.fhdl import verilog
class ColorPWM(Module):
"""PWM dimming for RGB332 Colors"""
def __init__(self):
maxPwm=6
self.pixUpper = Signal(8)
self.pixLower = Signal(8)
self.output = Signal(6)
self.resetCounter = Signal()
self.incrementCounter = Signal()
pwmCounter = Signal(max=maxPwm+1)
self.sync += If( self.resetCounter,
pwmCounter.eq(0)
).Elif(self.incrementCounter,
If((pwmCounter == maxPwm),
pwmCounter.eq(0)
).Else(
pwmCounter.eq(pwmCounter + 1)
)
)
r1, r2, g1, g2, b1, b2 = [Signal() for _ in range(6)]
self.comb += r1.eq(self.pixUpper[5:8] > pwmCounter)
self.comb += r2.eq(self.pixLower[5:8] > pwmCounter)
self.comb += g1.eq(self.pixUpper[2:5] > pwmCounter)
self.comb += g2.eq(self.pixLower[2:5] > pwmCounter)
self.comb += b1.eq(self.pixUpper[0:2] > pwmCounter[1:3])
self.comb += b2.eq(self.pixLower[0:2] > pwmCounter[1:3])
self.comb += self.output.eq(Cat(r1, r2, g1, g2, b1, b2))
class Hub75Sender(Module):
"""Hub75 LED Matrix driver. Framebuffer Colorformat RGB332"""
def __init__(self, numCols=8, numRows=4, content=None):
addressOffset = Constant(numCols * numRows/2)
rowCountShift = math.ceil(math.log2(numCols))
@ -17,20 +49,20 @@ class Hub75Sender(Module):
ram = self.mem.get_port()
self.specials += ram
pwm = ColorPWM()
self.submodules += pwm
# Pixel and Row counter
self.pixCount = Signal(max=numCols+1)
self.rowCount = Signal(max=numRows)
# Temporary Pixeldata register
self.pixUpper = Signal(8)
self.pixLower = Signal(8)
# Output Ports
self.outAddr = Signal(6) # abcde
self.outClk = Signal()
self.outOe = Signal()
self.outLat = Signal()
self.outRGB = Signal(8) # (6) r0 r1 g0 g1 b0 b1
self.outRGB = Signal(6) # (6) r0 r1 g0 g1 b0 b1
self.comb += self.outRGB.eq(pwm.output),
fsm = FSM(reset_state="RESET")
self.submodules.fsm = fsm
@ -38,6 +70,7 @@ class Hub75Sender(Module):
fsm.act("RESET",
NextValue(self.pixCount, 0),
NextValue(self.outOe, 1),
pwm.resetCounter.eq(1),
NextState("AdrUp"))
fsm.act("AdrUp", # Address upper Pixel
@ -47,25 +80,19 @@ class Hub75Sender(Module):
fsm.act("AdrLo", # Address lower Pixel + Readout Upper Pixel data
ram.adr.eq((self.pixCount + addressOffset) + (self.rowCount << rowCountShift)),
NextValue(self.pixCount, self.pixCount+1),
self.pixUpper.eq(ram.dat_r),
NextValue(pwm.pixUpper, ram.dat_r),
NextState("ReadLow"))
fsm.act("ReadLow", # Readout Lower Pixel data
self.pixLower.eq(ram.dat_r),
self.pixUpper.eq(self.pixUpper),
# Set Output
self.outRGB.eq(Cat(self.pixUpper[0:4], self.pixLower[0:4])),
NextValue(pwm.pixLower, ram.dat_r),
NextState("ClkOn"))
fsm.act("ClkOn", # Clock the Data out
self.outRGB.eq(self.outRGB),
self.outClk.eq(1),
NextValue(self.outClk, 1),
NextState("ClkOff"))
fsm.act("ClkOff", # Clock the Data out
self.outRGB.eq(self.outRGB),
NextValue(self.outClk, 0),
If(self.pixCount == numCols,
NextValue(self.outOe, 0),
NextValue(self.rowCount, self.rowCount + 1),
@ -83,23 +110,25 @@ class Hub75Sender(Module):
fsm.act("OeOn",
If(self.rowCount == Constant(numRows/2),
NextValue(self.rowCount, 0),
pwm.incrementCounter.eq(1),
NextState("Done")
).Else(
NextState("AdrUp"))
)
fsm.act("Done", NextState("Done"))
fsm.act("Done", NextState("AdrUp"))
def testbench():
content = (0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
content = (0x00, 0x01, 0x02, 0x03, 0x14, 0x15, 0x16, 0x17,
0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1c,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f)
dut = Hub75Sender(6, 8, content)
dut = Hub75Sender(4, 4, content)
def memtest():
for _ in range(200):
for _ in range(500):
yield
yield

Loading…
Cancel
Save