mac-rom-simm-programmer/usb_serial/usb_serial.c

382 lines
9.4 KiB
C
Raw Normal View History

/*
* usb_serial.c
*
* Created on: Dec 9, 2011
* Author: Doug
*/
#include "usb_serial.h"
#include "../LUFA/Drivers/USB/USB.h"
#include "../Descriptors.h"
#include "../external_mem.h"
2011-12-11 16:35:53 +00:00
#include "../tests/simm_electrical_test.h"
2011-12-17 04:13:34 +00:00
#define CHIP_SIZE (512UL * 1024UL)
2011-12-11 16:35:53 +00:00
#define READ_CHUNK_SIZE_BYTES 1024UL
2011-12-17 04:13:34 +00:00
#define WRITE_CHUNK_SIZE_BYTES 1024UL
2011-12-11 16:35:53 +00:00
#if ((READ_CHUNK_SIZE_BYTES % 4) != 0)
#error Read chunk size should be a multiple of 4 bytes
#endif
2011-12-17 04:13:34 +00:00
#if ((WRITE_CHUNK_SIZE_BYTES % 4) != 0)
#error Write chunk size should be a multiple of 4 bytes
#endif
USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
{
.Config =
{
.ControlInterfaceNumber = 0,
.DataINEndpointNumber = CDC_TX_EPNUM,
.DataINEndpointSize = CDC_TXRX_EPSIZE,
2011-12-11 16:35:53 +00:00
.DataINEndpointDoubleBank = true,
.DataOUTEndpointNumber = CDC_RX_EPNUM,
.DataOUTEndpointSize = CDC_TXRX_EPSIZE,
2011-12-11 16:35:53 +00:00
.DataOUTEndpointDoubleBank = true,
.NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,
.NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,
.NotificationEndpointDoubleBank = false,
},
};
void USBSerial_Init(void)
{
USB_Init();
}
2011-12-11 16:35:53 +00:00
typedef enum ProgrammerCommandState
{
WaitingForCommand = 0,
ReadingByteWaitingForAddress,
ReadingChips,
ReadingChipsUnableSendError,
2011-12-17 04:13:34 +00:00
WritingChips,
2011-12-11 16:35:53 +00:00
} ProgrammerCommandState;
typedef enum ProgrammerCommand
{
EnterWaitingMode = 0,
DoElectricalTest,
IdentifyChips,
ReadByte,
ReadChips,
EraseChips,
WriteChips,
} ProgrammerCommand;
typedef enum ProgrammerReply
{
2011-12-17 04:13:34 +00:00
CommandReplyOK,
CommandReplyError,
CommandReplyInvalid,
} ProgrammerReply;
2011-12-11 16:35:53 +00:00
2011-12-17 04:13:34 +00:00
typedef enum ComputerReadReply
{
ComputerReadOK,
ComputerReadCancel,
} ComputerReadReply;
typedef enum ProgrammerReadReply
{
ProgrammerReadOK,
ProgrammerReadError,
ProgrammerReadMoreData,
ProgrammerReadFinished,
ProgrammerReadConfirmCancel,
} ProgrammerReadReply;
typedef enum ComputerWriteReply
{
ComputerWriteMore,
ComputerWriteFinish,
ComputerWriteCancel,
} ComputerWriteReply;
typedef enum ProgrammerWriteReply
{
ProgrammerWriteOK,
ProgrammerWriteError,
ProgrammerWriteConfirmCancel,
};
2011-12-11 16:35:53 +00:00
static ProgrammerCommandState curCommandState = WaitingForCommand;
static uint8_t byteAddressReceiveCount = 0;
static uint16_t curReadIndex;
2011-12-17 04:13:34 +00:00
static int16_t writePosInChunk = -1;
static uint16_t curWriteIndex = 0;
2011-12-11 16:35:53 +00:00
void USBSerial_HandleWaitingForCommandByte(uint8_t byte);
2011-12-17 04:13:34 +00:00
void USBSerial_HandleReadingChipsByte(uint8_t byte);
2011-12-11 16:35:53 +00:00
void USBSerial_SendReadDataChunk(void);
2011-12-17 04:13:34 +00:00
void USBSerial_HandleWritingChipsByte(uint8_t byte);
#define SendByte(b) CDC_Device_SendByte(&VirtualSerial_CDC_Interface, b)
#define ReadByte() CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface)
#define SendData(d, l) CDC_Device_SendData(&VirtualSerial_CDC_Interface, d, l)
2011-12-11 16:35:53 +00:00
void USBSerial_Check(void)
{
2011-12-17 04:13:34 +00:00
/*if (USB_DeviceState == DEVICE_STATE_Configured)
{
if (CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface))
{
uint8_t rb = (uint8_t)CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
if (rb == 'i')
{
struct ChipID chips[4];
ExternalMem_IdentifyChips(chips);
char tmp[20];
uint32_t data = ExternalMem_ReadCycle(0);
int x;
for (x = 0; x < 4; x++)
{
sprintf(tmp, "IC%d: M%02X, D%02X\r\n", x+1, chips[x].manufacturerID, chips[x].deviceID);
CDC_Device_SendString(&VirtualSerial_CDC_Interface, tmp);
}
sprintf(tmp, "%08lX\r\n", data);
CDC_Device_SendString(&VirtualSerial_CDC_Interface, tmp);
}
else if (rb == 'e')
{
ExternalMem_EraseChips(ALL_CHIPS);
CDC_Device_SendString(&VirtualSerial_CDC_Interface, "Erased\r\n");
}
else if (rb == 'r')
{
uint32_t result = ExternalMem_ReadCycle(0);
char tmp[20];
sprintf(tmp, "%08lX\r\n", result);
CDC_Device_SendString(&VirtualSerial_CDC_Interface, tmp);
}
else if (rb == 'w')
{
uint32_t address = 0;
uint32_t x;
uint32_t y;
CDC_Device_SendString(&VirtualSerial_CDC_Interface, "Writing...\r\n");
CDC_Device_Flush(&VirtualSerial_CDC_Interface);
for (y = 0; y < 512UL*1024UL / (READ_CHUNK_SIZE_BYTES/4); y++)
{
for (x = 0; x < READ_CHUNK_SIZE_BYTES/4; x++)
{
ExternalMem_WriteByteToChips(address++, 0x12345678, ALL_CHIPS);
}
}
//ExternalMem_WriteByteToChips(0, 0x12345678UL, ALL_CHIPS);
CDC_Device_SendString(&VirtualSerial_CDC_Interface, "Wrote\r\n");
}
else if (rb == 't')
{
int result = SIMMElectricalTest_Run();
char tmp[20];
CDC_Device_SendString(&VirtualSerial_CDC_Interface, "SIMM electrical test complete: ");
sprintf(tmp, "%d errors\r\n", result);
CDC_Device_SendString(&VirtualSerial_CDC_Interface, tmp);
}
else if (rb == 'a')
{
uint32_t x;
CDC_Device_SendString(&VirtualSerial_CDC_Interface, "Reading...\r\n");
CDC_Device_Flush(&VirtualSerial_CDC_Interface);
for (x = 0; x < 512UL*1024UL; x++)
{
ExternalMem_ReadCycle(x);
}
CDC_Device_SendString(&VirtualSerial_CDC_Interface, "Finished\r\n");
}
}
2011-12-17 04:13:34 +00:00
}*/
2011-12-17 04:13:34 +00:00
if (USB_DeviceState == DEVICE_STATE_Configured)
2011-12-11 16:35:53 +00:00
{
// Check for commands, etc...
2011-12-17 04:13:34 +00:00
int16_t recvByte = ReadByte();
2011-12-11 16:35:53 +00:00
if (recvByte >= 0)
{
switch (curCommandState)
{
case WaitingForCommand:
USBSerial_HandleWaitingForCommandByte((uint8_t)recvByte);
break;
2011-12-17 04:13:34 +00:00
case ReadingChips:
USBSerial_HandleReadingChipsByte((uint8_t)recvByte);
break;
case WritingChips:
USBSerial_HandleWritingChipsByte((uint8_t)recvByte);
break;
2011-12-11 16:35:53 +00:00
}
}
2011-12-17 04:13:34 +00:00
}
2011-12-11 16:35:53 +00:00
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
USB_USBTask();
}
2011-12-11 16:35:53 +00:00
void USBSerial_HandleWaitingForCommandByte(uint8_t byte)
{
switch (byte)
{
case EnterWaitingMode:
curCommandState = WaitingForCommand;
break;
case DoElectricalTest:
2011-12-17 04:13:34 +00:00
SendByte(CommandReplyOK);
2011-12-11 16:35:53 +00:00
SIMMElectricalTest_Run();
curCommandState = WaitingForCommand;
break;
case IdentifyChips:
{
struct ChipID chips[4];
2011-12-17 04:13:34 +00:00
SendByte(CommandReplyOK);
2011-12-11 16:35:53 +00:00
ExternalMem_IdentifyChips(chips);
// TODO: Send chip ID info back to receiver
break;
}
case ReadByte:
curCommandState = ReadingByteWaitingForAddress;
byteAddressReceiveCount = 0;
2011-12-17 04:13:34 +00:00
SendByte(CommandReplyOK);
2011-12-11 16:35:53 +00:00
break;
case ReadChips:
curCommandState = ReadingChips;
curReadIndex = 0;
2011-12-17 04:13:34 +00:00
SendByte(CommandReplyOK);
2011-12-11 16:35:53 +00:00
USBSerial_SendReadDataChunk();
break;
case EraseChips:
2011-12-17 04:13:34 +00:00
ExternalMem_EraseChips(ALL_CHIPS);
SendByte(CommandReplyOK);
break;
2011-12-11 16:35:53 +00:00
case WriteChips:
2011-12-17 04:13:34 +00:00
curCommandState = WritingChips;
curWriteIndex = 0;
writePosInChunk = -1;
SendByte(CommandReplyOK);
break;
default:
SendByte(CommandReplyInvalid);
break;
}
}
void USBSerial_HandleReadingChipsByte(uint8_t byte)
{
switch (byte)
{
case ComputerReadOK:
if (curReadIndex >= (CHIP_SIZE / READ_CHUNK_SIZE_BYTES))
{
SendByte(ProgrammerReadFinished);
curCommandState = WaitingForCommand;
}
else
{
SendByte(ProgrammerReadMoreData);
USBSerial_SendReadDataChunk();
}
break;
case ComputerReadCancel:
SendByte(ProgrammerReadConfirmCancel);
curCommandState = WaitingForCommand;
2011-12-11 16:35:53 +00:00
break;
}
}
void USBSerial_SendReadDataChunk(void)
{
// TODO: How do I send an error back to the device?
// Maybe the device, when it tries to request the next data chunk,
// will get an ERROR response instead of an "OK" response?
static union
{
uint32_t readChunks[READ_CHUNK_SIZE_BYTES / 4];
uint8_t readChunkBytes[READ_CHUNK_SIZE_BYTES];
} chunks;
ExternalMem_Read(curReadIndex * (READ_CHUNK_SIZE_BYTES/4), chunks.readChunks, READ_CHUNK_SIZE_BYTES/4);
2011-12-17 04:13:34 +00:00
uint8_t retVal = SendData((const char *)chunks.readChunkBytes, READ_CHUNK_SIZE_BYTES);
2011-12-11 16:35:53 +00:00
if (retVal != ENDPOINT_RWSTREAM_NoError)
{
curCommandState = ReadingChipsUnableSendError;
}
else
{
curReadIndex++;
}
}
2011-12-17 04:13:34 +00:00
void USBSerial_HandleWritingChipsByte(uint8_t byte)
{
static union
{
uint32_t writeChunks[WRITE_CHUNK_SIZE_BYTES / 4];
uint8_t writeChunkBytes[WRITE_CHUNK_SIZE_BYTES];
} chunks;
if (writePosInChunk == -1)
{
switch (byte)
{
case ComputerWriteMore:
writePosInChunk = 0;
if (curWriteIndex < CHIP_SIZE / WRITE_CHUNK_SIZE_BYTES)
{
SendByte(ProgrammerWriteOK);
}
else
{
SendByte(ProgrammerWriteError);
}
break;
case ComputerWriteFinish:
// Just to confirm that we finished writing...
SendByte(ProgrammerWriteOK);
curCommandState = WaitingForCommand;
break;
case ComputerWriteCancel:
SendByte(ProgrammerWriteConfirmCancel);
curCommandState = WaitingForCommand;
break;
}
}
else
{
chunks.writeChunkBytes[writePosInChunk++] = byte;
if (writePosInChunk >= WRITE_CHUNK_SIZE_BYTES)
{
// Write this data
ExternalMem_Write(curWriteIndex * (WRITE_CHUNK_SIZE_BYTES/4), chunks.writeChunks, WRITE_CHUNK_SIZE_BYTES/4, ALL_CHIPS);
SendByte(ProgrammerWriteOK);
curWriteIndex++;
writePosInChunk = -1;
}
}
}
2011-12-11 16:35:53 +00:00
/** Event handler for the library USB Configuration Changed event. */
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
ConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
}
/** Event handler for the library USB Control Request reception event. */
void EVENT_USB_Device_ControlRequest(void)
{
CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
}