aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjaseg <jaseg@jaseg.net>2013-12-17 13:52:40 +0100
committerjaseg <jaseg@jaseg.net>2013-12-17 13:52:40 +0100
commitb1e665ed8d5ddd4f5596e06f38e612681ffbfadc (patch)
treebf83872289d460137d4b86e08626a7f45485dc5c
parent27ecd8933fd8b2a9c28a088ba30bafc14f5736a5 (diff)
downloadmatelight-b1e665ed8d5ddd4f5596e06f38e612681ffbfadc.tar.gz
matelight-b1e665ed8d5ddd4f5596e06f38e612681ffbfadc.tar.bz2
matelight-b1e665ed8d5ddd4f5596e06f38e612681ffbfadc.zip
More robust error handling, USB-triggered frame latching
-rw-r--r--firmware/main.c89
-rw-r--r--firmware/startup_gcc.c3
2 files changed, 47 insertions, 45 deletions
diff --git a/firmware/main.c b/firmware/main.c
index 3c8e000..4419435 100644
--- a/firmware/main.c
+++ b/firmware/main.c
@@ -103,21 +103,6 @@ void SysTickIntHandler(void) {
g_ulSysTickCount++;
}
-/* Will be called when a DMA transfer is complete */
-void SSI0IntHandler(void) {
- /* FIXME is this necessary? */
- unsigned long ssistatus = SSIIntStatus(SSI0_BASE, 1);
- MAP_SSIIntClear(SSI0_BASE, ssistatus);
-
- if(!MAP_uDMAChannelIsEnabled(11)){
- /* A TX DMA transfer was completed */
- /* FIXME actually, just set a flag here and kick off when all four controllers signal completion.*/
- /* Wait 1.2ms for the WS2801s to latch (the datasheet specifies at least 500µs) */
- MAP_SysCtlDelay(20000);
- kickoff_transfers();
- }
-}
-
unsigned long RxHandler(void *pvCBData, unsigned long ulEvent, unsigned long ulMsgValue, void *pvMsgData) {
switch(ulEvent) {
case USB_EVENT_CONNECTED:
@@ -142,48 +127,68 @@ unsigned long RxHandler(void *pvCBData, unsigned long ulEvent, unsigned long ulM
}
typedef struct {
+ unsigned char command; /* 0x00 for frame data, 0x01 to initiate latch */
unsigned char crate_x;
unsigned char crate_y;
unsigned char rgb_data[CRATE_SIZE*BYTES_PER_PIXEL];
} FramebufferData;
unsigned long framebuffer_read(void *data, unsigned long len) {
- if(len != sizeof(FramebufferData))
- return len;
+ if(len < 1)
+ goto length_error;
UARTprintf("Rearranging data.\n");
FramebufferData *fb = (FramebufferData *)data;
+ if(fb->command == 1){
+ if(len != 1)
+ goto length_error;
+ UARTprintf("Starting DMA.\n");
+ kickoff_transfers();
+ }else{
+ if(len != sizeof(FramebufferData))
+ goto length_error;
- unsigned int bus = fb->crate_x/CRATES_X;
- fb->crate_x %= CRATES_X;
+ unsigned int bus = fb->crate_x/CRATES_X;
+ fb->crate_x %= CRATES_X;
- if(bus > BUS_COUNT || fb->crate_y > CRATES_Y){
- UARTprintf("Invalid frame index\n");
- return len;
- }
+ if(bus > BUS_COUNT || fb->crate_y > CRATES_Y){
+ UARTprintf("Invalid frame index\n");
+ return len;
+ }
- /* Mirror crate map for the display's right half */
- if(bus >= BUS_COUNT/2)
- fb->crate_x = CRATES_X - fb->crate_x - 1;
-
- unsigned int crate = CRATE_MAP[fb->crate_x + fb->crate_y*CRATES_X];
- for(unsigned int x=0; x<CRATE_WIDTH; x++){
- for(unsigned int y=0; y<CRATE_HEIGHT; y++){
- unsigned int bottle = BOTTLE_MAP[x + y*CRATE_WIDTH];
- unsigned int dst = bus*BUS_SIZE + (crate*CRATE_SIZE + bottle)*3;
- unsigned int src = (y*CRATE_WIDTH + x)*3;
- /* Copy r, g and b data */
- framebuffer_input[dst] = fb->rgb_data[src];
- framebuffer_input[dst + 1] = fb->rgb_data[src + 1];
- framebuffer_input[dst + 2] = fb->rgb_data[src + 2];
+ /* Mirror crate map for the display's right half */
+ if(bus >= BUS_COUNT/2)
+ fb->crate_x = CRATES_X - fb->crate_x - 1;
+
+ unsigned int crate = CRATE_MAP[fb->crate_x + fb->crate_y*CRATES_X];
+ for(unsigned int x=0; x<CRATE_WIDTH; x++){
+ for(unsigned int y=0; y<CRATE_HEIGHT; y++){
+ unsigned int bottle = BOTTLE_MAP[x + y*CRATE_WIDTH];
+ unsigned int dst = bus*BUS_SIZE + (crate*CRATE_SIZE + bottle)*3;
+ unsigned int src = (y*CRATE_WIDTH + x)*3;
+ /* Copy r, g and b data */
+ framebuffer_input[dst] = fb->rgb_data[src];
+ framebuffer_input[dst + 1] = fb->rgb_data[src + 1];
+ framebuffer_input[dst + 2] = fb->rgb_data[src + 2];
+ }
}
}
-
- UARTprintf("Starting DMA.\n");
- kickoff_transfers();
+ return len;
+length_error:
+ UARTprintf("Invalid packet length\n");
return len;
}
void kickoff_transfers() {
+ while(MAP_uDMAChannelIsEnabled(11)
+ || MAP_uDMAChannelIsEnabled(25)
+ || MAP_uDMAChannelIsEnabled(13)
+ || MAP_uDMAChannelIsEnabled(15)){
+ UARTprintf("A DMA tranfer is still running\n");
+ /* Idle for some time to give the µDMA controller a chance to complete its job */
+ SysCtlDelay(5000);
+ }
+ /* Wait 1.2ms (20kCy @ 50MHz) to ensure the WS2801 latch this frame's data */
+ SysCtlDelay(20000);
/* Swap buffers */
unsigned char *tmp = framebuffer_output;
framebuffer_output = framebuffer_input;
@@ -195,7 +200,7 @@ void kickoff_transfers() {
kickoff_transfer(15, 3, SSI3_BASE);
}
-void kickoff_transfer(unsigned int channel, unsigned int offset, int base) {
+inline void kickoff_transfer(unsigned int channel, unsigned int offset, int base) {
MAP_uDMAChannelTransferSet(channel | UDMA_PRI_SELECT, UDMA_MODE_BASIC, framebuffer_output+BUS_SIZE*offset, (void *)(base + SSI_O_DR), BUS_SIZE);
MAP_uDMAChannelEnable(channel);
}
@@ -302,8 +307,6 @@ int main(void) {
MAP_SSIDMAEnable(SSI2_BASE, SSI_DMA_TX);
MAP_SSIDMAEnable(SSI3_BASE, SSI_DMA_TX);
- MAP_IntEnable(INT_SSI0);
-
/* Enable the SSIs after configuring anything around them. */
MAP_SSIEnable(SSI0_BASE);
MAP_SSIEnable(SSI1_BASE);
diff --git a/firmware/startup_gcc.c b/firmware/startup_gcc.c
index 8c7a44d..b9284ad 100644
--- a/firmware/startup_gcc.c
+++ b/firmware/startup_gcc.c
@@ -43,7 +43,6 @@ static void IntDefaultHandler(void);
extern void SysTickIntHandler(void);
extern void UARTStdioIntHandler(void);
extern void USB0DeviceIntHandler(void);
-extern void SSI0IntHandler(void);
//*****************************************************************************
//
@@ -92,7 +91,7 @@ void (* const g_pfnVectors[])(void) =
IntDefaultHandler, // GPIO Port E
UARTStdioIntHandler, // UART0 Rx and Tx
IntDefaultHandler, // UART1 Rx and Tx
- SSI0IntHandler, // SSI0 Rx and Tx
+ IntDefaultHandler, // SSI0 Rx and Tx
IntDefaultHandler, // I2C0 Master and Slave
IntDefaultHandler, // PWM Fault
IntDefaultHandler, // PWM Generator 0