mirror of
https://github.com/dougg3/mac-rom-simm-programmer.git
synced 2024-11-25 10:30:49 +00:00
Tried to do some better commenting in usb_serial.c, also tried to do a better job of documenting the protocol in programmer_protocol.h
This commit is contained in:
parent
147c2bfda3
commit
7f69cb476d
38
main.c
38
main.c
@ -19,6 +19,7 @@ int main(void)
|
|||||||
DDRD |= (1 << 7);
|
DDRD |= (1 << 7);
|
||||||
PORTD &= ~(1 << 7);
|
PORTD &= ~(1 << 7);
|
||||||
|
|
||||||
|
// If there was a brownout detected, turn on the LED momentarily
|
||||||
if (MCUSR & (1 << BORF))
|
if (MCUSR & (1 << BORF))
|
||||||
{
|
{
|
||||||
MCUSR = 0;
|
MCUSR = 0;
|
||||||
@ -39,42 +40,5 @@ int main(void)
|
|||||||
USBSerial_Check();
|
USBSerial_Check();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*int result = SIMMElectricalTest_Run();
|
|
||||||
|
|
||||||
if (result == 0)
|
|
||||||
{
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
_delay_ms(200);
|
|
||||||
PIND = (1 << 7);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
int tmpResult = result;
|
|
||||||
|
|
||||||
while (tmpResult)
|
|
||||||
{
|
|
||||||
int thisDigit = (tmpResult % 10) + 1;
|
|
||||||
|
|
||||||
while (thisDigit--)
|
|
||||||
{
|
|
||||||
PIND = (1 << 7);
|
|
||||||
_delay_ms(500);
|
|
||||||
PIND = (1 << 7);
|
|
||||||
_delay_ms(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
_delay_ms(2000);
|
|
||||||
|
|
||||||
tmpResult /= 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
_delay_ms(5000);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -115,4 +115,23 @@ typedef enum BootloaderStateReply
|
|||||||
BootloaderStateInProgrammer
|
BootloaderStateInProgrammer
|
||||||
} BootloaderStateReply;
|
} BootloaderStateReply;
|
||||||
|
|
||||||
|
// ------------------------- BOOTLOADER ERASE/WRITE PROTOCOL -------------------------
|
||||||
|
// If the command is BootloaderEraseAndWriteProgram, it will reply with CommandReplyOK
|
||||||
|
// followed by either BootloaderEraseOK or BootloaderEraseError. At this point
|
||||||
|
// the program can ask to write more data or finish or cancel, and then the appropriate
|
||||||
|
// reply will be sent back to it. Works very similar to the write protocol.
|
||||||
|
typedef enum ProgrammerBootloaderEraseWriteReply
|
||||||
|
{
|
||||||
|
BootloaderWriteOK,
|
||||||
|
BootloaderWriteError,
|
||||||
|
BootloaderWriteConfirmCancel
|
||||||
|
} ProgrammerBootloaderEraseWriteReply;
|
||||||
|
|
||||||
|
typedef enum ComputerBootloaderEraseWriteRequest
|
||||||
|
{
|
||||||
|
ComputerBootloaderWriteMore = 0,
|
||||||
|
ComputerBootloaderFinish,
|
||||||
|
ComputerBootloaderCancel
|
||||||
|
} ComputerBootloaderEraseWriteRequest;
|
||||||
|
|
||||||
#endif /* PROGRAMMER_PROTOCOL_H_ */
|
#endif /* PROGRAMMER_PROTOCOL_H_ */
|
||||||
|
@ -27,6 +27,7 @@ void USBSerial_Init(void)
|
|||||||
USB_Init();
|
USB_Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal state so we know how to interpret the next-received byte
|
||||||
typedef enum ProgrammerCommandState
|
typedef enum ProgrammerCommandState
|
||||||
{
|
{
|
||||||
WaitingForCommand = 0,
|
WaitingForCommand = 0,
|
||||||
@ -35,107 +36,37 @@ typedef enum ProgrammerCommandState
|
|||||||
ReadingChipsUnableSendError,
|
ReadingChipsUnableSendError,
|
||||||
WritingChips
|
WritingChips
|
||||||
} ProgrammerCommandState;
|
} ProgrammerCommandState;
|
||||||
|
|
||||||
static ProgrammerCommandState curCommandState = WaitingForCommand;
|
static ProgrammerCommandState curCommandState = WaitingForCommand;
|
||||||
|
|
||||||
|
// State info for reading/writing
|
||||||
static uint8_t byteAddressReceiveCount = 0;
|
static uint8_t byteAddressReceiveCount = 0;
|
||||||
static uint16_t curReadIndex;
|
static uint16_t curReadIndex;
|
||||||
static int16_t writePosInChunk = -1;
|
static int16_t writePosInChunk = -1;
|
||||||
static uint16_t curWriteIndex = 0;
|
static uint16_t curWriteIndex = 0;
|
||||||
|
|
||||||
|
// Private functions
|
||||||
void USBSerial_HandleWaitingForCommandByte(uint8_t byte);
|
void USBSerial_HandleWaitingForCommandByte(uint8_t byte);
|
||||||
void USBSerial_HandleReadingChipsByte(uint8_t byte);
|
void USBSerial_HandleReadingChipsByte(uint8_t byte);
|
||||||
void USBSerial_SendReadDataChunk(void);
|
void USBSerial_SendReadDataChunk(void);
|
||||||
void USBSerial_HandleWritingChipsByte(uint8_t byte);
|
void USBSerial_HandleWritingChipsByte(uint8_t byte);
|
||||||
void USBSerial_ElectricalTest_Fail_Handler(uint8_t index1, uint8_t index2);
|
void USBSerial_ElectricalTest_Fail_Handler(uint8_t index1, uint8_t index2);
|
||||||
|
|
||||||
|
// Read/write to USB serial macros -- easier than retyping
|
||||||
|
// CDC_Device_XXX(&VirtualSerial_CDC_Interface...) every time
|
||||||
#define SendByte(b) CDC_Device_SendByte(&VirtualSerial_CDC_Interface, b)
|
#define SendByte(b) CDC_Device_SendByte(&VirtualSerial_CDC_Interface, b)
|
||||||
#define ReadByte() CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface)
|
#define ReadByte() CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface)
|
||||||
#define SendData(d, l) CDC_Device_SendData(&VirtualSerial_CDC_Interface, d, l)
|
#define SendData(d, l) CDC_Device_SendData(&VirtualSerial_CDC_Interface, d, l)
|
||||||
|
|
||||||
|
// Should be called periodically in the main loop
|
||||||
void USBSerial_Check(void)
|
void USBSerial_Check(void)
|
||||||
{
|
{
|
||||||
/*if (USB_DeviceState == DEVICE_STATE_Configured)
|
// If we're configured, read a byte (if one is available) and process it
|
||||||
{
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (USB_DeviceState == DEVICE_STATE_Configured)
|
if (USB_DeviceState == DEVICE_STATE_Configured)
|
||||||
{
|
{
|
||||||
// Check for commands, etc...
|
|
||||||
int16_t recvByte = ReadByte();
|
int16_t recvByte = ReadByte();
|
||||||
|
|
||||||
|
// Did we get a byte? If so, hand it off to the correct handler
|
||||||
|
// function based on the current state
|
||||||
if (recvByte >= 0)
|
if (recvByte >= 0)
|
||||||
{
|
{
|
||||||
switch (curCommandState)
|
switch (curCommandState)
|
||||||
@ -153,24 +84,30 @@ void USBSerial_Check(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// And do the periodic CDC and USB tasks...
|
||||||
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
|
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
|
||||||
USB_USBTask();
|
USB_USBTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're in the "waiting for command" state, handle the command...
|
||||||
void USBSerial_HandleWaitingForCommandByte(uint8_t byte)
|
void USBSerial_HandleWaitingForCommandByte(uint8_t byte)
|
||||||
{
|
{
|
||||||
switch (byte)
|
switch (byte)
|
||||||
{
|
{
|
||||||
|
// Asked to enter waiting mode -- we're already there, so say OK.
|
||||||
case EnterWaitingMode:
|
case EnterWaitingMode:
|
||||||
SendByte(CommandReplyOK);
|
SendByte(CommandReplyOK);
|
||||||
curCommandState = WaitingForCommand;
|
curCommandState = WaitingForCommand;
|
||||||
break;
|
break;
|
||||||
|
// Asked to do the electrical test. Reply OK, and then do the test,
|
||||||
|
// sending whatever replies necessary
|
||||||
case DoElectricalTest:
|
case DoElectricalTest:
|
||||||
SendByte(CommandReplyOK);
|
SendByte(CommandReplyOK);
|
||||||
SIMMElectricalTest_Run(USBSerial_ElectricalTest_Fail_Handler);
|
SIMMElectricalTest_Run(USBSerial_ElectricalTest_Fail_Handler);
|
||||||
SendByte(ProgrammerElectricalTestDone);
|
SendByte(ProgrammerElectricalTestDone);
|
||||||
curCommandState = WaitingForCommand;
|
curCommandState = WaitingForCommand;
|
||||||
break;
|
break;
|
||||||
|
// Asked to identify the chips in the SIMM. Identify them and send reply.
|
||||||
case IdentifyChips:
|
case IdentifyChips:
|
||||||
{
|
{
|
||||||
struct ChipID chips[4];
|
struct ChipID chips[4];
|
||||||
@ -185,91 +122,120 @@ void USBSerial_HandleWaitingForCommandByte(uint8_t byte)
|
|||||||
SendByte(ProgrammerIdentifyDone);
|
SendByte(ProgrammerIdentifyDone);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Asked to read a single byte from each SIMM. Change the state and reply.
|
||||||
case ReadByte:
|
case ReadByte:
|
||||||
curCommandState = ReadingByteWaitingForAddress;
|
curCommandState = ReadingByteWaitingForAddress;
|
||||||
byteAddressReceiveCount = 0;
|
byteAddressReceiveCount = 0;
|
||||||
SendByte(CommandReplyOK);
|
SendByte(CommandReplyOK);
|
||||||
break;
|
break;
|
||||||
|
// Asked to read all four chips. Set the state, reply with the first chunk
|
||||||
case ReadChips:
|
case ReadChips:
|
||||||
curCommandState = ReadingChips;
|
curCommandState = ReadingChips;
|
||||||
curReadIndex = 0;
|
curReadIndex = 0;
|
||||||
SendByte(CommandReplyOK);
|
SendByte(CommandReplyOK);
|
||||||
USBSerial_SendReadDataChunk();
|
USBSerial_SendReadDataChunk();
|
||||||
break;
|
break;
|
||||||
|
// Erase the chips and reply OK. (TODO: Sometimes erase might fail)
|
||||||
case EraseChips:
|
case EraseChips:
|
||||||
ExternalMem_EraseChips(ALL_CHIPS);
|
ExternalMem_EraseChips(ALL_CHIPS);
|
||||||
SendByte(CommandReplyOK);
|
SendByte(CommandReplyOK);
|
||||||
break;
|
break;
|
||||||
|
// Begin writing the chips. Change the state, reply, wait for chunk of data
|
||||||
case WriteChips:
|
case WriteChips:
|
||||||
curCommandState = WritingChips;
|
curCommandState = WritingChips;
|
||||||
curWriteIndex = 0;
|
curWriteIndex = 0;
|
||||||
writePosInChunk = -1;
|
writePosInChunk = -1;
|
||||||
SendByte(CommandReplyOK);
|
SendByte(CommandReplyOK);
|
||||||
break;
|
break;
|
||||||
|
// Asked for the current bootloader state. We are in the program right now,
|
||||||
|
// so reply accordingly.
|
||||||
case GetBootloaderState:
|
case GetBootloaderState:
|
||||||
SendByte(CommandReplyOK);
|
SendByte(CommandReplyOK);
|
||||||
SendByte(BootloaderStateInProgrammer);
|
SendByte(BootloaderStateInProgrammer);
|
||||||
break;
|
break;
|
||||||
|
// Enter the bootloader. Wait a bit, then jump to the bootloader location.
|
||||||
case EnterBootloader:
|
case EnterBootloader:
|
||||||
SendByte(CommandReplyOK);
|
SendByte(CommandReplyOK);
|
||||||
|
|
||||||
|
// Done with the USB interface -- the bootloader will re-initialize it.
|
||||||
USB_Disable();
|
USB_Disable();
|
||||||
|
|
||||||
// Disable interrupts...
|
// Disable interrupts so nothing weird happens...
|
||||||
cli();
|
cli();
|
||||||
|
|
||||||
// Wait a little bit to let everything settle and let the program close the port after the USB disconnect
|
// Wait a little bit to let everything settle and let the program
|
||||||
|
// close the port after the USB disconnect
|
||||||
_delay_ms(2000);
|
_delay_ms(2000);
|
||||||
|
|
||||||
// Now run the bootloader
|
// And, of course, go into the bootloader.
|
||||||
__asm__ __volatile__ ( "jmp 0xE000" );
|
__asm__ __volatile__ ( "jmp 0xE000" );
|
||||||
break;
|
break;
|
||||||
|
// Enter the programmer. We're already there, so reply OK.
|
||||||
case EnterProgrammer:
|
case EnterProgrammer:
|
||||||
// Already in the programmer
|
// Already in the programmer
|
||||||
SendByte(CommandReplyOK);
|
SendByte(CommandReplyOK);
|
||||||
break;
|
break;
|
||||||
|
// We don't know what this command is, so reply that it was invalid.
|
||||||
default:
|
default:
|
||||||
SendByte(CommandReplyInvalid);
|
SendByte(CommandReplyInvalid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're in the "reading chips" state, handle the incoming byte...
|
||||||
void USBSerial_HandleReadingChipsByte(uint8_t byte)
|
void USBSerial_HandleReadingChipsByte(uint8_t byte)
|
||||||
{
|
{
|
||||||
|
// The byte should be a reply from the computer. It should be either:
|
||||||
|
// 1) ComputerReadOK -- meaning it got the chunk we just sent
|
||||||
|
// or
|
||||||
|
// 2) ComputerReadCancel -- meaning the user canceled the read
|
||||||
switch (byte)
|
switch (byte)
|
||||||
{
|
{
|
||||||
case ComputerReadOK:
|
case ComputerReadOK:
|
||||||
|
// If they have confirmed the final data chunk, let them know
|
||||||
|
// that they have finished, and enter command state.
|
||||||
if (curReadIndex >= (CHIP_SIZE / (READ_CHUNK_SIZE_BYTES/4)))
|
if (curReadIndex >= (CHIP_SIZE / (READ_CHUNK_SIZE_BYTES/4)))
|
||||||
{
|
{
|
||||||
SendByte(ProgrammerReadFinished);
|
SendByte(ProgrammerReadFinished);
|
||||||
curCommandState = WaitingForCommand;
|
curCommandState = WaitingForCommand;
|
||||||
}
|
}
|
||||||
else
|
else // There's more data left to read, so read it and send it to them!
|
||||||
{
|
{
|
||||||
SendByte(ProgrammerReadMoreData);
|
SendByte(ProgrammerReadMoreData);
|
||||||
USBSerial_SendReadDataChunk();
|
USBSerial_SendReadDataChunk();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ComputerReadCancel:
|
case ComputerReadCancel:
|
||||||
|
// If they've canceled, let them know we got their request and go back
|
||||||
|
// to "waiting for command" state
|
||||||
SendByte(ProgrammerReadConfirmCancel);
|
SendByte(ProgrammerReadConfirmCancel);
|
||||||
curCommandState = WaitingForCommand;
|
curCommandState = WaitingForCommand;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read the next chunk of data from the SIMM and send it off over the serial.
|
||||||
void USBSerial_SendReadDataChunk(void)
|
void USBSerial_SendReadDataChunk(void)
|
||||||
{
|
{
|
||||||
// TODO: How do I send an error back to the device?
|
// Here's a buffer we will use to read the next chunk of data.
|
||||||
// Maybe the device, when it tries to request the next data chunk,
|
// It's static because the stack is NOT big enough for it. If I start
|
||||||
// will get an ERROR response instead of an "OK" response?
|
// running low on RAM, I could pull this out of the function and share it
|
||||||
|
// with other functions, but I'm not bothering with that for now.
|
||||||
static union
|
static union
|
||||||
{
|
{
|
||||||
uint32_t readChunks[READ_CHUNK_SIZE_BYTES / 4];
|
uint32_t readChunks[READ_CHUNK_SIZE_BYTES / 4];
|
||||||
uint8_t readChunkBytes[READ_CHUNK_SIZE_BYTES];
|
uint8_t readChunkBytes[READ_CHUNK_SIZE_BYTES];
|
||||||
} chunks;
|
} chunks;
|
||||||
|
|
||||||
ExternalMem_Read(curReadIndex * (READ_CHUNK_SIZE_BYTES/4), chunks.readChunks, READ_CHUNK_SIZE_BYTES/4);
|
// Read the next chunk of data, send it over USB, and make sure
|
||||||
uint8_t retVal = SendData((const char *)chunks.readChunkBytes, READ_CHUNK_SIZE_BYTES);
|
// we sent it correctly.
|
||||||
|
ExternalMem_Read(curReadIndex * (READ_CHUNK_SIZE_BYTES/4),
|
||||||
|
chunks.readChunks, READ_CHUNK_SIZE_BYTES/4);
|
||||||
|
uint8_t retVal = SendData((const char *)chunks.readChunkBytes,
|
||||||
|
READ_CHUNK_SIZE_BYTES);
|
||||||
|
|
||||||
|
// If for some reason there was an error, mark it as such. Otherwise,
|
||||||
|
// increment our pointer so we know the next chunk of data to send.
|
||||||
if (retVal != ENDPOINT_RWSTREAM_NoError)
|
if (retVal != ENDPOINT_RWSTREAM_NoError)
|
||||||
{
|
{
|
||||||
curCommandState = ReadingChipsUnableSendError;
|
curCommandState = ReadingChipsUnableSendError;
|
||||||
@ -280,20 +246,30 @@ void USBSerial_SendReadDataChunk(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handles a received byte from the computer while we're in the "writing chips"
|
||||||
|
// mode.
|
||||||
void USBSerial_HandleWritingChipsByte(uint8_t byte)
|
void USBSerial_HandleWritingChipsByte(uint8_t byte)
|
||||||
{
|
{
|
||||||
|
// A buffer we use to store the incoming data. This, too, could be shared
|
||||||
|
// with other functions if I end up running out of RAM. Again, I'm not
|
||||||
|
// bothering with that yet, but this could easily be shared with the
|
||||||
|
// read function.
|
||||||
static union
|
static union
|
||||||
{
|
{
|
||||||
uint32_t writeChunks[WRITE_CHUNK_SIZE_BYTES / 4];
|
uint32_t writeChunks[WRITE_CHUNK_SIZE_BYTES / 4];
|
||||||
uint8_t writeChunkBytes[WRITE_CHUNK_SIZE_BYTES];
|
uint8_t writeChunkBytes[WRITE_CHUNK_SIZE_BYTES];
|
||||||
} chunks;
|
} chunks;
|
||||||
|
|
||||||
|
// This means we have just started the entire process or just finished
|
||||||
|
// a chunk, so see what the computer has decided for us to do.
|
||||||
if (writePosInChunk == -1)
|
if (writePosInChunk == -1)
|
||||||
{
|
{
|
||||||
switch (byte)
|
switch (byte)
|
||||||
{
|
{
|
||||||
|
// The computer asked to write more data to the SIMM.
|
||||||
case ComputerWriteMore:
|
case ComputerWriteMore:
|
||||||
writePosInChunk = 0;
|
writePosInChunk = 0;
|
||||||
|
// Make sure we don't write past the capacity of the chips.
|
||||||
if (curWriteIndex < CHIP_SIZE / (WRITE_CHUNK_SIZE_BYTES/4))
|
if (curWriteIndex < CHIP_SIZE / (WRITE_CHUNK_SIZE_BYTES/4))
|
||||||
{
|
{
|
||||||
SendByte(ProgrammerWriteOK);
|
SendByte(ProgrammerWriteOK);
|
||||||
@ -301,26 +277,31 @@ void USBSerial_HandleWritingChipsByte(uint8_t byte)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
SendByte(ProgrammerWriteError);
|
SendByte(ProgrammerWriteError);
|
||||||
|
// TODO: Enter waiting for command mode?
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// The computer said that it's done writing.
|
||||||
case ComputerWriteFinish:
|
case ComputerWriteFinish:
|
||||||
// Just to confirm that we finished writing...
|
|
||||||
SendByte(ProgrammerWriteOK);
|
SendByte(ProgrammerWriteOK);
|
||||||
curCommandState = WaitingForCommand;
|
curCommandState = WaitingForCommand;
|
||||||
break;
|
break;
|
||||||
|
// The computer asked to cancel.
|
||||||
case ComputerWriteCancel:
|
case ComputerWriteCancel:
|
||||||
SendByte(ProgrammerWriteConfirmCancel);
|
SendByte(ProgrammerWriteConfirmCancel);
|
||||||
curCommandState = WaitingForCommand;
|
curCommandState = WaitingForCommand;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // Interpret the incoming byte as data to write to the SIMM.
|
||||||
{
|
{
|
||||||
|
// Save the byte, and check if we've filled up an entire chunk
|
||||||
chunks.writeChunkBytes[writePosInChunk++] = byte;
|
chunks.writeChunkBytes[writePosInChunk++] = byte;
|
||||||
if (writePosInChunk >= WRITE_CHUNK_SIZE_BYTES)
|
if (writePosInChunk >= WRITE_CHUNK_SIZE_BYTES)
|
||||||
{
|
{
|
||||||
// Write this data
|
// We filled up the chunk, write it out and confirm it, then wait
|
||||||
ExternalMem_Write(curWriteIndex * (WRITE_CHUNK_SIZE_BYTES/4), chunks.writeChunks, WRITE_CHUNK_SIZE_BYTES/4, ALL_CHIPS);
|
// for the next command from the computer!
|
||||||
|
ExternalMem_Write(curWriteIndex * (WRITE_CHUNK_SIZE_BYTES/4),
|
||||||
|
chunks.writeChunks, WRITE_CHUNK_SIZE_BYTES/4, ALL_CHIPS);
|
||||||
SendByte(ProgrammerWriteOK);
|
SendByte(ProgrammerWriteOK);
|
||||||
curWriteIndex++;
|
curWriteIndex++;
|
||||||
writePosInChunk = -1;
|
writePosInChunk = -1;
|
||||||
@ -328,18 +309,17 @@ void USBSerial_HandleWritingChipsByte(uint8_t byte)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whenever an electrical test failure occurs, this handler will be called
|
||||||
|
// by it. It sends out a failure notice followed by indexes of the two
|
||||||
|
// shorted pins.
|
||||||
void USBSerial_ElectricalTest_Fail_Handler(uint8_t index1, uint8_t index2)
|
void USBSerial_ElectricalTest_Fail_Handler(uint8_t index1, uint8_t index2)
|
||||||
{
|
{
|
||||||
// Sends out a failure notice -- followed by indexes of the two shorted pins
|
|
||||||
SendByte(ProgrammerElectricalTestFail);
|
SendByte(ProgrammerElectricalTestFail);
|
||||||
SendByte(index1);
|
SendByte(index1);
|
||||||
SendByte(index2);
|
SendByte(index2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LUFA event handler for when the USB configuration changes.
|
||||||
|
|
||||||
|
|
||||||
/** Event handler for the library USB Configuration Changed event. */
|
|
||||||
void EVENT_USB_Device_ConfigurationChanged(void)
|
void EVENT_USB_Device_ConfigurationChanged(void)
|
||||||
{
|
{
|
||||||
bool ConfigSuccess = true;
|
bool ConfigSuccess = true;
|
||||||
@ -347,7 +327,7 @@ void EVENT_USB_Device_ConfigurationChanged(void)
|
|||||||
ConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
|
ConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Event handler for the library USB Control Request reception event. */
|
// LUFA event handler for when a USB control request is received
|
||||||
void EVENT_USB_Device_ControlRequest(void)
|
void EVENT_USB_Device_ControlRequest(void)
|
||||||
{
|
{
|
||||||
CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
|
CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
|
||||||
|
Loading…
Reference in New Issue
Block a user