279 lines
7.2 KiB
C
279 lines
7.2 KiB
C
/* *************************************
|
|
* Includes
|
|
* *************************************/
|
|
|
|
#include "Serial.h"
|
|
|
|
/* *************************************
|
|
* Defines
|
|
* *************************************/
|
|
|
|
#define SERIAL_BAUDRATE 115200
|
|
#define SERIAL_TX_RX_TIMEOUT 20000
|
|
#define SERIAL_RX_FIFO_EMPTY 0
|
|
#define SERIAL_TX_NOT_READY 0
|
|
|
|
/* *************************************
|
|
* Local Variables
|
|
* *************************************/
|
|
|
|
static volatile SERIAL_STATE SerialState;
|
|
static volatile size_t bytesRead;
|
|
static volatile uint32_t initPC_Address;
|
|
static volatile uint32_t RAMDest_Address;
|
|
static volatile size_t ExeSize;
|
|
static volatile size_t totalBytes;
|
|
static volatile size_t exeBytesRead;
|
|
static volatile bool serial_busy;
|
|
|
|
/* *************************************
|
|
* Local Prototypes
|
|
* *************************************/
|
|
|
|
void ISR_Serial(void)
|
|
{
|
|
enum
|
|
{
|
|
SERIAL_BG_X0 = 0,
|
|
SERIAL_BG_X1 = X_SCREEN_RESOLUTION - SERIAL_BG_X0,
|
|
SERIAL_BG_X2 = SERIAL_BG_X0,
|
|
SERIAL_BG_X3 = SERIAL_BG_X1,
|
|
|
|
SERIAL_BG_Y0 = 0,
|
|
SERIAL_BG_Y1 = SERIAL_BG_Y0,
|
|
SERIAL_BG_Y2 = Y_SCREEN_RESOLUTION - SERIAL_BG_Y0,
|
|
SERIAL_BG_Y3 = SERIAL_BG_Y2,
|
|
|
|
SERIAL_BG_R = 0,
|
|
SERIAL_BG_G = NORMAL_LUMINANCE,
|
|
SERIAL_BG_B = NORMAL_LUMINANCE,
|
|
};
|
|
|
|
static GsGPoly4 SerialBg = { .x[0] = SERIAL_BG_X0,
|
|
.x[1] = SERIAL_BG_X1,
|
|
.x[2] = SERIAL_BG_X2,
|
|
.x[3] = SERIAL_BG_X3,
|
|
|
|
.y[0] = SERIAL_BG_Y0,
|
|
.y[1] = SERIAL_BG_Y1,
|
|
.y[2] = SERIAL_BG_Y2,
|
|
.y[3] = SERIAL_BG_Y3,
|
|
|
|
.r[0] = 0,
|
|
.r[1] = 0,
|
|
.r[2] = SERIAL_BG_R,
|
|
.r[3] = SERIAL_BG_R,
|
|
|
|
.g[0] = 0,
|
|
.g[1] = 0,
|
|
.g[2] = SERIAL_BG_G,
|
|
.g[3] = SERIAL_BG_G,
|
|
|
|
.b[0] = 0,
|
|
.b[1] = 0,
|
|
.b[2] = SERIAL_BG_B,
|
|
.b[3] = SERIAL_BG_B, };
|
|
|
|
enum
|
|
{
|
|
SERIAL_STATE_TEXT_X = 148,
|
|
SERIAL_STATE_TEXT_Y = Y_SCREEN_RESOLUTION >> 1,
|
|
};
|
|
|
|
SystemIncreaseGlobalTimer();
|
|
|
|
if( (GfxIsGPUBusy() == true) || (SystemIsBusy() == true) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
FontSetFlags(&SmallFont, FONT_BLEND_EFFECT | FONT_H_CENTERED);
|
|
|
|
if(SerialState == SERIAL_STATE_READING_EXE_DATA)
|
|
{
|
|
if(System1SecondTick() == false)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
FontSetFlags(&SmallFont, FONT_H_CENTERED);
|
|
}
|
|
}
|
|
|
|
GsSortGPoly4(&SerialBg);
|
|
|
|
switch(SerialState)
|
|
{
|
|
case SERIAL_STATE_INIT:
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Serial initialization");
|
|
break;
|
|
|
|
case SERIAL_STATE_STANDBY:
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Waiting for PC...");
|
|
break;
|
|
|
|
case SERIAL_STATE_WRITING_ACK:
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Writing ACK");
|
|
break;
|
|
|
|
case SERIAL_STATE_READING_HEADER:
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Reading data from header (%d/%d bytes)...", bytesRead, totalBytes);
|
|
break;
|
|
|
|
case SERIAL_STATE_READING_EXE_SIZE:
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Getting PSX-EXE size from PC...");
|
|
break;
|
|
|
|
case SERIAL_STATE_READING_EXE_DATA:
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Reading PSX-EXE data (%d/%d bytes)...", exeBytesRead, ExeSize);
|
|
break;
|
|
|
|
case SERIAL_STATE_WAITING_USER_INPUT:
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Press any key to continue");
|
|
break;
|
|
|
|
case SERIAL_STATE_CLEANING_MEMORY:
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Cleaning RAM before EXE data transfer...");
|
|
break;
|
|
|
|
default:
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Unknown state");
|
|
break;
|
|
}
|
|
|
|
FontSetFlags(&SmallFont, FONT_H_CENTERED);
|
|
|
|
if(RAMDest_Address != 0)
|
|
{
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y + 16, "RAM Dest address: 0x%08X", RAMDest_Address);
|
|
}
|
|
|
|
if(initPC_Address != 0)
|
|
{
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y + 32, "Init PC address: 0x%08X", initPC_Address);
|
|
}
|
|
|
|
if(ExeSize != 0)
|
|
{
|
|
FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y + 48, "PSX-EXE size: 0x%08X", ExeSize);
|
|
}
|
|
|
|
GfxDrawScene_Fast();
|
|
}
|
|
|
|
void SerialSetState(SERIAL_STATE state)
|
|
{
|
|
SerialState = state;
|
|
}
|
|
|
|
void SerialSetPCAddress(uint32_t addr)
|
|
{
|
|
initPC_Address = addr;
|
|
}
|
|
|
|
void SerialSetRAMDestAddress(uint32_t addr)
|
|
{
|
|
RAMDest_Address = addr;
|
|
}
|
|
|
|
void SerialSetExeSize(size_t size)
|
|
{
|
|
ExeSize = size;
|
|
}
|
|
|
|
void SerialInit(void)
|
|
{
|
|
uint8_t receivedBytes;
|
|
|
|
SetVBlankHandler(&ISR_Serial);
|
|
|
|
SerialState = SERIAL_STATE_INIT;
|
|
|
|
SIOStart(SERIAL_BAUDRATE);
|
|
|
|
SerialState = SERIAL_STATE_STANDBY;
|
|
|
|
// ------------------------------------
|
|
// Protocol description
|
|
// ------------------------------------
|
|
|
|
// 1. Wait to receive magic byte "99" from PC.
|
|
|
|
SerialRead(&receivedBytes, sizeof(uint8_t) );
|
|
|
|
if(receivedBytes != 99)
|
|
{
|
|
dprintf("Did not receive input magic number!\n");
|
|
return;
|
|
}
|
|
|
|
// 2. Send ACK (magic byte is ASCII code for 'b').
|
|
|
|
SerialState = SERIAL_STATE_WRITING_ACK;
|
|
|
|
SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t) );
|
|
}
|
|
|
|
void SerialSetExeBytesReceived(uint32_t bytes_read)
|
|
{
|
|
exeBytesRead += bytes_read;
|
|
}
|
|
|
|
bool SerialRead(uint8_t* ptrArray, size_t nBytes)
|
|
{
|
|
bytesRead = 0;
|
|
totalBytes = nBytes;
|
|
|
|
serial_busy = true;
|
|
|
|
if(nBytes == 0)
|
|
{
|
|
SerialWrite("SerialRead: invalid size %d\n", strnlen("SerialRead: invalid size %d\n", 30));
|
|
return false;
|
|
}
|
|
|
|
do
|
|
{
|
|
//uint16_t timeout = SERIAL_TX_RX_TIMEOUT;
|
|
|
|
while( (SIOCheckInBuffer() == SERIAL_RX_FIFO_EMPTY)); // Wait for RX FIFO not empty
|
|
|
|
*(ptrArray++) = SIOReadByte();
|
|
bytesRead++;
|
|
}while(--nBytes);
|
|
|
|
serial_busy = false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SerialWrite(void* ptrArray, size_t nBytes)
|
|
{
|
|
serial_busy = true;
|
|
|
|
SystemDisableVBlankInterrupt();
|
|
|
|
if(nBytes == 0)
|
|
{
|
|
SerialWrite("SerialRead: invalid size %d\n", strnlen("SerialRead: invalid size %d\n", 30));
|
|
return false;
|
|
}
|
|
|
|
do
|
|
{
|
|
//uint16_t timeout = SERIAL_TX_RX_TIMEOUT;
|
|
|
|
while( (SIOCheckOutBuffer() == SERIAL_TX_NOT_READY)); // Wait for TX FIFO empty.
|
|
|
|
SIOSendByte(*(uint8_t*)ptrArray++);
|
|
|
|
}while(--nBytes);
|
|
|
|
SystemEnableVBlankInterrupt();
|
|
|
|
serial_busy = false;
|
|
|
|
return true;
|
|
}
|