Up w/ cool running(s)!

master
kaqu 2 years ago
parent 29ea25083e
commit 751975db71
  1. 85
      neopixelengine.py
  2. 61
      software/source/illumination.c
  3. 3
      software/source/main.c

@ -33,18 +33,24 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
Usage:
######
#. Fill NeoPixelEngine's local array of GRB values (Green/Red/Blue)
1. Freeze operations by setting ``bEnable`` to false (0)
2. Fill NeoPixelEngine's local array of GRB values (Green/Red/Blue)
from DRAM location
Load ``b32DRAMAddress`` with a 32-bit DRAM memory pointer.
Indicate the offset (where to store) via writing to ``b6StoreOffset``.
Repeat for all DRAM address 'til end of array ...
#. Indicate no. of DRAM addresses stored by writing to ``b6NoOfTables``
3. Indicate no. of DRAM addresses stored by writing the # to ``b6NoOfTables``
#. Indicate to NeoPixelEngine the actual no. of pixels used by setting up ``b9Len``.
4. Indicate to NeoPixelEngine the actual no. of pixels used by setting up ``b9Len``.
For now, all arrays have to have the same max. length.
#. Finally, enable processing by setting ``bEnable`` to true (1).
5. Finally, enable processing by setting ``bEnable`` to true (1).
6. NPE processing will now run async. to CPU until reset or s.a. (1.).
CPU from now on will write to DRAM only (yet, L2 cache will have to be flushed),
all data will be picked up by FPGA automatically ...
Inputs:
#######
@ -107,8 +113,9 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
self.b9Offset = Signal(9) # Array rover (0..511)
self.b32GRB = Signal(32) # Current 24-bit(GRB) or 32-bit (GRBW) data to send
self.b12PulseLen = Signal(12) # Current pulse length
self.b5Count24 = Signal(5) # 24-Bit (or 32-bit) counter
self.b5Count24 = Signal(5) # 24-Bit (TODO: or 32-bit) counter
self.b32BaseAddress = Signal(32) # Base DRAM address
storage = Memory(32, n_TABLES) # * n_LEDs)
self.specials += storage
wrport = storage.get_port(write_capable=True)
@ -121,43 +128,67 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
rdport = storage.get_port()
self.specials += rdport
self.comb += [ # Read from DRAM addresses memory
rdport.adr.eq(self.b6Table) # Index DRAM address array (READ) # TODO: Not used currently!
rdport.adr.eq(self.b6Table) # Index DRAM address array (READ)
]
if dramtransfer != None: # This is for real!
self.sync += dramtransfer.b9Offset.storage.eq(self.b9Offset) # Index DRAM data value storage
# Output
self.bDataPin = Array(Signal(1) for bit in range(16)) # To be wired to data pins ...
# TODO: Expand to 60 outputs ...
self.bDataPin = Array(Signal(1) for bit in range(64)) # To be wired to data pins ...
###
fsm = FSM(reset_state="IDLETABLE") # FSM starts idling ...
self.submodules += fsm
fsm.act("IDLETABLE",
If((self.bEnable.storage==True) and (self.b9Len.storage > 0),
NextValue(self.b6Table, 0), # Start @ 1st table
NextValue(self.b6Table, 0), # Start @ 1st (DRAM) table data
NextValue(self.b9Offset, 0), # Start @ 1st 24-bit or 32-bit data (mem will be ready next cycle)
NextValue(self.b5Count24, 0), # Bit count 0..23 (or 0..31)
NextState("IDLE1")
NextValue(self.b5Count24, 0), # Bit count 0..23 (TODO: or 0..31)
NextState("TABLELOADLOOP")
)
)
fsm.act("TABLELOADLOOP", # 1st cycle delay for memory port access
NextState("TABLELOAD2")
)
fsm.act("TABLELOAD2", # DRAM address now selected (avail.), hence pull it!
NextValue(self.b32BaseAddress, rdport.dat_r), # Depends upon b6Table
NextState("TABLELOAD3")
)
fsm.act("TABLELOAD3", # Load from DRAM address
NextValue(dramtransfer.b32Address.storage, self.b32BaseAddress),
NextState("TABLELOAD4")
)
fsm.act("TABLELOAD4", # Engage!
NextValue(dramtransfer.bEnable.storage, 1),
NextState("TABLELOADWAIT")
)
fsm.act("TABLELOADWAIT", # Wait for termination of transfer ...
If(dramtransfer.bValid.storage, # Data avail.?
NextValue(dramtransfer.bEnable.storage, 0), # Reset/ACK to DRAM transfer (sort of ...)
NextState("GRBWORDLOOP") # Yap!
)
# TODO: Permit timeout indication ...
)
# G/R/B Word loop entry:
fsm.act("IDLE1", # 1st cycle delay for memory port access
fsm.act("GRBWORDLOOP", # 1st cycle delay for memory port access
NextState("IDLE2")
)
fsm.act("IDLE2", # 2nd cycle delay ...
NextState("IDLE3")
)
fsm.act("IDLE3",
#NextValue(self.b32GRB, rdport.dat_r), # Depends upon b6Table/b9Offset
#if dramtransfer != None:
NextValue(self.b32GRB, dramtransfer.b32Data.storage), # Depends upon b9Offset
NextValue(self.b5Count24, 0), # Bit count 0..23 (or 0..31)
fsm.act("IDLE3",
NextValue(self.b32GRB, dramtransfer.b32Data.storage), # Depends upon b9Offset
NextValue(self.b5Count24, 0), # Bit count 0..23 (TODO: or 0..31)
NextState("PREPAREBIT")
)
# 24-bit or 32-bit loop entry:
# 24-bit (TODO: or 32-bit) loop entry:
# Protocol: T0H=400ns/T0L=850ns, T1H=800ns/T1L=450ns, RST>50µs(>50000ns)
fsm.act("PREPAREBIT",
If(self.b32GRB[23],
@ -227,11 +258,9 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
fsm.act("NEXTWORD2",
NextState("NEXTWORD3") # Add one cycle for read port propagation!
)
fsm.act("NEXTWORD3",
fsm.act("NEXTWORD3",
If((self.b9Offset < self.b9Len.storage) & (self.bEnable.storage==True), # Still more words to come (& no exit request)?
#NextValue(self.b32GRB, rdport.dat_r), # Depends upon b6Table/b9Offset!
#if dramtransfer != None:
NextValue(self.b32GRB, dramtransfer.b32Data.storage), # Depends upon b9Offset!
NextValue(self.b32GRB, dramtransfer.b32Data.storage), # Depends upon b9Offset!
NextState("PREPAREBIT")
).Else(
NextValue(self.b12PulseLen, 4095), # >50µs required (3000 not ok!)
@ -249,15 +278,15 @@ class NeoPixelEngine(Module, AutoCSR, AutoDoc, ModuleDoc):
fsm.act("NEXTTABLE",
If(self.b6Table < self.b6NoOfTables.storage,
NextValue(self.b9Offset, 0), # Start @ 1st 24-bit data (or 32-bit data)
NextState("IDLE1")
).Else(
NextValue(self.b9Offset, 0), # Start @ 1st 24-bit data (TODO: or 32-bit data)
NextState("TABLELOADLOOP") # Bring in next DRAM table
).Else( # Final table: Restart!
NextState("IDLETABLE")
)
)
def npe_testbench(npe):
def npe_testbench(npe): # TODO: Make it work again ...
print("----- npe testbench -----")
yield npe.b4LoadTable.storage.eq(0)
yield

@ -44,8 +44,8 @@
#include "../include/illumination.h"
extern void busy_wait(unsigned int ms); // Worx!
#define MAXTABLES 3 // 1..16 MUST match h/w!
#define MAXLEDS 27 // 1..256 MUST match h/w!
#define MAXTABLES 2 // 0..63 MUST match h/w!
#define MAXLEDS 32 //27 // 1..256 MUST match h/w!
static int32_t arLEDBuffer[MAXTABLES][MAXLEDS] __attribute__((aligned(16)));; // GRB values
extern char kbhit(void);
@ -70,26 +70,35 @@ int key_eval(void)
void enable_LEDS(int iEnable)
{
npe_b6NoOfTables_write(MAXTABLES); // Prepare # of tables
npe_b9Len_write(MAXLEDS); // Prepare length
npe_bEnable_write(iEnable ? 1 : 0); // Enable/disable
}
void send_LEDs(void)
{
for(int j=0;j<MAXTABLES;j++) {
npe_b6StoreOffset_write(j); // Indicate which entry to use for address storage
npe_b32DRAMAddress_write((uint32_t)&arLEDBuffer[j]); // Base address of LED buffer
static uint32_t uiLoopCount = 0;
if(iEnable) {
npe_b6NoOfTables_write(MAXTABLES); // Prepare # of tables
npe_b9Len_write(MAXLEDS); // Prepare length
for(int j=0;j<MAXTABLES;j++) {
printf("DRAM->[%d] = %08Xh\n", j, (uint32_t)&arLEDBuffer[j]);
npe_b6StoreOffset_write(j); // Indicate which entry to use for address storage
npe_b32DRAMAddress_write((uint32_t)&arLEDBuffer[j]); // Base address of LED buffer
}
uiLoopCount = dramtransfer_b32RCount_read();
}
else {
printf("Disabling NPE, transfer count %d w/ %d tables of length %d\n",
dramtransfer_b32RCount_read() - uiLoopCount, MAXTABLES, MAXLEDS);
}
if(!load_FPGA((uint32_t)&arLEDBuffer[0], 0)) // Load <n> bytes from 0x40190000 ... (16 byte aligned!)
printf("*** send_LEDs(): load_FPGA() failed?!\n");
flush_l2_cache(); // Strictly nec. for longer transfers
busy_wait(10); // Testing still ...
npe_bEnable_write(iEnable ? 1 : 0); // Enable/disable
}
void clear_LEDs(int iTable)
{
for(int i=0;i<MAXLEDS;i++)
arLEDBuffer[iTable][i] = 0;
flush_l2_cache(); // Strictly nec. for longer transfers
}
void load_triple_LEDs(int iTable, int32_t green, int32_t red, int32_t blue)
@ -99,6 +108,7 @@ void load_triple_LEDs(int iTable, int32_t green, int32_t red, int32_t blue)
arLEDBuffer[iTable][i+1] = red;
arLEDBuffer[iTable][i+2] = blue;
}
flush_l2_cache(); // Strictly nec. for longer transfers
}
int illumination(void)
@ -117,8 +127,7 @@ int illumination(void)
load_triple_LEDs(iTable, red, blue, green);
iTable = 2;
load_triple_LEDs(iTable, blue, green, red);
send_LEDs();
enable_LEDS(1);
enable_LEDS(1); // Engage!
busy_wait(2000);
// Let them flicker ...
@ -129,7 +138,6 @@ int illumination(void)
blue = temp;
for(iTable=0;iTable<MAXTABLES;iTable++)
load_triple_LEDs(iTable, green, red, blue);
send_LEDs();
busy_wait(iDelay); // Slow down a bit
if(key_eval()) {
enable_LEDS(0);
@ -137,18 +145,25 @@ int illumination(void)
}
}
// Make 3 run along ...
green = 0x404000;
red = 0x004040;
blue = 0x400040;
for(iTable=0;iTable<MAXTABLES;iTable++) {
clear_LEDs(iTable); // Reset buffers
if(iTable != 0) {
green = 0x404000;
red = 0x004040;
blue = 0x400040;
}
else {
green = 0x040000;
red = 0x000400;
blue = 0x000004;
}
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();
flush_l2_cache(); // Strictly nec. for longer transfers
busy_wait(iDelay);
for(iTable=0;iTable<MAXTABLES;iTable++) {
for(int j=0;j<max_LED;j++)
@ -162,7 +177,7 @@ int illumination(void)
}
printf("Halfway thru ...\n");
for(int i=0;i<MAXLEDS-1;i++) { // Backward shift 3
send_LEDs();
flush_l2_cache(); // Strictly nec. for longer transfers
busy_wait(iDelay);
for(iTable=0;iTable<MAXTABLES;iTable++) {
for(int j=0;j<max_LED;j++)
@ -174,12 +189,14 @@ int illumination(void)
return 1;
}
}
flush_l2_cache(); // Strictly nec. for longer transfers
busy_wait(400);
// Prepare final output
for(iTable=0;iTable<MAXTABLES;iTable++)
load_triple_LEDs(iTable, 0x010000, 0x000100, 0x000001); // 1st load
send_LEDs();
flush_l2_cache(); // Strictly nec. for longer transfers
busy_wait(500);
enable_LEDS(0);
printf("Finished!\n");

@ -73,6 +73,7 @@ int main(int i, char **c)
#endif
setsystime(14, 30, 00); // Reset to defined value (14:30) ...
#ifdef XXXX
// Prepare first output
int32_t green = 0x040201;
int32_t red = 0x010402;
@ -89,7 +90,7 @@ int main(int i, char **c)
enable_LEDS(1);
busy_wait(2000);
enable_LEDS(0);
#endif
uart_init();
printf("\n");

Loading…
Cancel
Save