Block adressing corrected, still 0-LED fault ...

master
kaqu 2 years ago
parent b08b5a983a
commit 95a1b0fa9e
  1. 71
      firmware/main.c
  2. 43
      neopixelengine.py
  3. 43205
      npe.vcd

@ -70,14 +70,14 @@ static void boot_sequence(void)
//------------------- Illumination demo --------------------------------
extern void busy_wait(unsigned int ms);
#define MAXTABLES 16
#define MAXLEDS 27 // MUST match h/w!
static int32_t arLEDBuffer[MAXLEDS]; // GRB values
#define MAXTABLES 3 // 16
#define MAXLEDS 27 // 256 MUST match h/w!
static int32_t arLEDBuffer[MAXTABLES][MAXLEDS]; // GRB values
void enable_LEDS(int iEnable)
{
npe_b8Len_write(MAXLEDS); // Prepare length
npe_bEnable_write(iEnable?1:0); // Enable/disable
npe_bEnable_write(iEnable ? 1 : 0); // Enable/disable
}
void send_LEDs()
@ -86,27 +86,25 @@ void send_LEDs()
npe_b4LoadTable_write(j);
for(int i=0;i<MAXLEDS;i++) {
npe_b8LoadOffset_write(i); // @Offset
npe_b24Data2Load_write(arLEDBuffer[i]); // store 32(24) bit value
npe_b24Data2Load_write(arLEDBuffer[j][i]); // store 32(24) bit value
}
}
busy_wait(25); // Minimum that meets the eye ;)
}
void clear_LEDs()
void clear_LEDs(int iTable)
{
for(int i=0;i<MAXLEDS;i++)
arLEDBuffer[i] = 0;
send_LEDs();
arLEDBuffer[iTable][i] = 0;
}
void load_triple_LEDs(int32_t green, int32_t red, int32_t blue)
void load_triple_LEDs(int iTable, int32_t green, int32_t red, int32_t blue)
{
for(int i=0;i<MAXLEDS;i+=3) {
arLEDBuffer[i] = green;
arLEDBuffer[i+1] = red;
arLEDBuffer[i+2] = blue;
}
send_LEDs();
arLEDBuffer[iTable][i] = green;
arLEDBuffer[iTable][i+1] = red;
arLEDBuffer[iTable][i+2] = blue;
}
}
void illumination()
@ -114,11 +112,18 @@ void illumination()
int32_t green = 0x040000;
int32_t red = 0x000400;
int32_t blue = 0x000004;
int iTable;
// Prepare first output
load_triple_LEDs(green, red, blue); // 1st load
iTable = 0;
load_triple_LEDs(iTable, green, red, blue); // 1st load
iTable = 1;
load_triple_LEDs(iTable, red, blue, green);
iTable = 2;
load_triple_LEDs(iTable, blue, green, red);
send_LEDs();
enable_LEDS(1);
busy_wait(1000);
busy_wait(2000);
// Let them flicker ...
for(int i=0;i<MAXLEDS;i++) {
@ -126,36 +131,46 @@ void illumination()
green = red;
red = blue;
blue = temp;
load_triple_LEDs(green,red,blue);
for(iTable=0;iTable<MAXTABLES;iTable++)
load_triple_LEDs(iTable, green, red, blue);
send_LEDs();
busy_wait(80); // Slow down a bit
}
// Make 3 run along ...
clear_LEDs(); // Mainly to reset buffer
green = 0x400000;
red = 0x004000;
blue = 0x000040;
arLEDBuffer[0] = green;
arLEDBuffer[1] = red;
arLEDBuffer[2] = blue;
for(iTable=0;iTable<MAXTABLES;iTable++) {
clear_LEDs(iTable); // Reset buffers
arLEDBuffer[iTable][0] = green;
arLEDBuffer[iTable][1] = red;
arLEDBuffer[iTable][2] = blue;
}
int max_LED = MAXLEDS-1; // 0..26
for(int i=0;i<MAXLEDS-3;i++) { // Forward shift 3
send_LEDs();
busy_wait(100);
for(int j=0;j<max_LED;j++)
arLEDBuffer[max_LED - j] = arLEDBuffer[(max_LED - 1) - j];
arLEDBuffer[i] = 0;
for(iTable=0;iTable<MAXTABLES;iTable++) {
for(int j=0;j<max_LED;j++)
arLEDBuffer[iTable][max_LED - j] = arLEDBuffer[iTable][(max_LED - 1) - j];
arLEDBuffer[iTable][i] = 0;
}
}
for(int i=0;i<MAXLEDS-1;i++) { // Backward shift 3
send_LEDs();
busy_wait(100);
for(int j=0;j<max_LED;j++)
arLEDBuffer[j] = arLEDBuffer[j+1];
arLEDBuffer[max_LED-i] = 0;
for(iTable=0;iTable<MAXTABLES;iTable++) {
for(int j=0;j<max_LED;j++)
arLEDBuffer[iTable][j] = arLEDBuffer[iTable][j+1];
arLEDBuffer[iTable][max_LED-i] = 0;
}
}
busy_wait(400);
// Prepare final output
load_triple_LEDs(0x010000, 0x000100, 0x000001); // 1st load
for(iTable=0;iTable<MAXTABLES;iTable++)
load_triple_LEDs(iTable, 0x010000, 0x000100, 0x000001); // 1st load
send_LEDs();
busy_wait(500);
enable_LEDS(0);
}

@ -105,23 +105,21 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
self.b8Offset = Signal(8) # Array rover
self.b24GRB = Signal(24) # Current 24-bit data to send
self.b12PulseLen = Signal(12) # Current pulse length
self.b5Count24 = Signal(5) # 24-Bit counter
self.b24GRBmem = Signal(24) # Readout local store
self.b5Count24 = Signal(5) # 24-Bit counter
storage = Memory(24, n_TABLES * n_LEDs)
self.specials += storage
wrport = storage.get_port(write_capable=True) #, clock_domain="write")
self.specials += wrport
self.comb += [ # Write to memory
wrport.adr.eq(self.b8LoadOffset.storage),
wrport.adr.eq((self.b4LoadTable.storage * n_LEDs) + self.b8LoadOffset.storage),
wrport.dat_w.eq(self.b24Data2Load.storage),
wrport.we.eq(1)
]
rdport = storage.get_port()
self.specials += rdport
self.comb += [ # Read from memory
rdport.adr.eq(self.b8Offset),
self.b24GRBmem.eq(rdport.dat_r)
rdport.adr.eq((self.b4Table * n_LEDs) + self.b8Offset)
]
# Output
@ -134,14 +132,14 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
fsm.act("IDLETABLE",
If((self.bEnable.storage==True) and (self.b8Len.storage > 0),
NextValue(self.b4Table, 0), # Start @ 1st table
NextValue(self.b8Offset, 0), # Start @ 1st 24-bit data (mem will be ready next cycle)
NextState("IDLE")
)
)
fsm.act("IDLE",
If((self.bEnable.storage==True) and (self.b8Len.storage > 0),
NextValue(self.b8Offset, 0), # Start @ 1st 24-bit data
NextValue(self.b24GRB, self.b24GRBmem), # Depends upon b8Offset (cycle?)
If((self.bEnable.storage==True) and (self.b8Len.storage > 0),
NextValue(self.b24GRB, rdport.dat_r), # Depends upon b4Table/b8Offset
NextValue(self.b5Count24, 0), # Bit count 0..23
NextState("PREPAREBIT")
)
@ -160,8 +158,12 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
fsm.act("T1H",
NextValue(self.bDataPin[self.b4Table], 1),
NextValue(self.b12PulseLen, self.b12PulseLen - 1),
If(self.b12PulseLen == 0,
NextValue(self.b12PulseLen, 24), # Compensate for 3 state changes w/o action ...
If(self.b12PulseLen == 0,
If(self.b5Count24 < 23, # Not final pulse of word
NextValue(self.b12PulseLen, 24) # Compensate for 3 state changes w/o action ...
).Else( # Final word pulse special
NextValue(self.b12PulseLen, 21) # Compensate word load cycles
),
NextState("T1L")
)
)
@ -179,7 +181,11 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
NextValue(self.bDataPin[self.b4Table], 1),
NextValue(self.b12PulseLen, self.b12PulseLen - 1),
If(self.b12PulseLen == 0,
NextValue(self.b12PulseLen, 48), # Compensate for 3 state changes w/o action ...
If(self.b5Count24 < 23, # Not final pulse of word?
NextValue(self.b12PulseLen, 48) # Compensate for 3 state changes w/o action ...
).Else( # Final word load special
NextValue(self.b12PulseLen, 45) # Compensate for load word cycles
),
NextState("T0L")
)
)
@ -199,12 +205,18 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
).Else( # GRB word finished. More to come?
NextValue(self.b5Count24,0), # Bit count reset for next word
NextValue(self.b8Offset, self.b8Offset + 1), # Prepare offset for later use
NextState("NEXTWORD")
NextState("NEXTWORD1")
)
)
fsm.act("NEXTWORD",
fsm.act("NEXTWORD1",
NextState("NEXTWORD2") # Add one cycle for read port propagation!
)
fsm.act("NEXTWORD2",
NextState("NEXTWORD3") # Add one cycle for read port propagation!
)
fsm.act("NEXTWORD3",
If((self.b8Offset < self.b8Len.storage) & (self.bEnable.storage==True), # Still more words to come (& no exit request)?
NextValue(self.b24GRB, self.b24GRBmem), # Depends upon b8Offset!
NextValue(self.b24GRB, rdport.dat_r), # Depends upon b4Table/b8Offset!
NextState("PREPAREBIT")
).Else(
NextValue(self.b12PulseLen, 4095), # >50µs required (3000 not ok!)
@ -221,7 +233,8 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
)
fsm.act("NEXTTABLE",
If(self.b4Table < 16,
If(self.b4Table < 16,
NextValue(self.b8Offset, 0), # Start @ 1st 24-bit data
NextState("IDLE")
).Else(
NextState("IDLETABLE")

43205
npe.vcd

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save