1
0
SEm-Labos/Libs/NanoBlaze/hdl/nanoTest.pas

369 lines
14 KiB
ObjectPascal
Raw Permalink Normal View History

2024-02-23 13:01:05 +00:00
{
beamer.pas
The beamer controller polls the UART to get commands and provides the
corresponding replies.
}
program BeamerControl;
{==============================================================================}
{ Constants }
{==============================================================================}
const
clockFrequency = 66E6;
gpioBaseAddress = $0000;
gpioDataOffset = $0000;
gpioEnableOffset = $0001;
uartBaseAddress = $0010;
uartBaudOffset = $0002;
uartStatusOffset = $0001;
uartDataReady = $0001;
uartSending = $0002;
uartBaudRate = 1E6;
uartBaudCount = clockFrequency / uartBaudRate;
uartPollDelay = uartBaudCount / 2;
uartTimeout = 10;
commandHeader = $AA;
commandNack = $00;
commandWriteMem = $03;
commandReadMem = $04;
commandWriteLength = 4;
commandReadLength = 2;
beamerBaseAddress = $0020;
beamerCtlOffset = $0000;
beamerSpeedOffset = $0001;
beamerCtlInit = $0401;
beamerSpeedInit = $0004;
commStIdle = $0000;
commStGetPacketId = $0001;
commStGetCommandId = $0002;
commStGetDataLength = $0003;
commStGetData = $0004;
commStGetChecksum = $0005;
commStExecuteCommand = $0006;
commStSendHeader = $0007;
commStSendPacketId = $0008;
commStSendCommandId = $0009;
commStSendDataLength = $000A;
commStSendData = $000B;
commStSendChecksum = $000C;
{==============================================================================}
{ Variables }
{==============================================================================}
var
communicationState : word;
uartByte: uint8;
{==============================================================================}
{ Procedures and functions }
{==============================================================================}
{============================================================================}
{ Register-level functions }
{============================================================================}
{----------------------------------------------------------------------------}
{ Registers initializations }
{----------------------------------------------------------------------------}
procedure initRegisters;
const
gpioValue = $AA;
gpioEnablemask = $0F;
begin
{ initialize GPIO }
mem[gpioBaseAddress+gpioDataOffset] := gpioValue;
mem[gpioBaseAddress+gpioEnableOffset] := gpioEnablemask;
{ initialize UART }
mem[uartBaseAddress+uartBaudOffset] := uartBaudCount;
{ initialize beamer peripheral }
mem[beamerBaseAddress+beamerCtlOffset] := beamerCtlInit;
mem[beamerBaseAddress+beamerSpeedOffset] := beamerSpeedInit;
end;
{----------------------------------------------------------------------------}
{ Get byte from serial port with timeout }
{----------------------------------------------------------------------------}
function getSerialPortByte(var uartByte: uint8) : word;
var
dataReady: uint8;
pollCount: word;
begin
{ poll until data byte available or timeout occured}
pollCount := uartPollDelay;
dataReady := 0;
while dataReady = 0 do
begin
{ read status register }
dataReady := mem[uartBaseAddress+uartStatusOffset] and uartDataReady;
{ spend time in order not to overcharge the AHB bus }
if dataReady = 0 then
begin
{ check for timeout }
pollCount := pollCount -1;
if pollCount = 0 then
dataReady := $FF;
{ spend time in order not to overcharge the system bus }
for index := 1 to uartPollDelay do
noOperation;
end;
end;
{ function return }
if dataReady = $FF then
{ return timeout }
getSerialPortByte := 1;
else
{ read data register and return it }
begin
uartByte := mem[uartBaseAddress];
getSerialPortByte := 0;
end;
end;
{----------------------------------------------------------------------------}
{ Send byte to serial port with timeout }
{----------------------------------------------------------------------------}
function sendSerialPort(var uartByte : uint8) : word;
var
dataReady: uint8;
statusByte: uint8;
pollCount: word;
begin
{ poll until ready to send }
pollCount := uartPollDelay;
statusByte := mem[uartBaseAddress+uartStatusOffset] and uartSending;
while statusByte = 0 do
begin
{ check for timeout }
pollCount := pollCount -1;
if pollCount = 0 then
dataReady := $FF;
{ spend time in order not to overcharge the system bus }
for index := 1 to uartPollDelay do
noOperation;
{ read status register }
statusByte := mem[uartBaseAddress+uartStatusOffset] and uartSending;
end;
{ function return }
if dataReady = $FF then
{ return timeout }
sendSerialPort := 1;
else
{ write data register and return it }
begin
mem[uartBaseAddress] := uartByte;
sendSerialPort := 0;
end;
end;
{============================================================================}
{ Communication state machine }
{============================================================================}
procedure updateStateMachine(
var communicationState : word;
var uartByte: uint8
);
var
communicationNextState : word;
uartStatus: word;
packetId, commandId : uint8;
checksum : uint8;
dataLength, dataCount, data1, data2, data3, data4 : uint8;
memAddress, memData : word;
begin
{ idle }
if communicationState = commStIdle then
begin
uartStatus := getSerialPortByte(var uartByte: uint8);
if (uartStatus = 0) and (uartByte = commandHeader) then
begin
checksum := uartByte;
communicationNextState := commStGetPacketId;
end;
end;
{ get packet id }
else if communicationState = commStGetPacketId then
begin
uartStatus := getSerialPortByte(var uartByte: uint8);
if uartStatus = 0 then
begin
packetId := uartByte;
checksum := checksum + uartByte;
communicationNextState := commStGetCommandId;
end;
end;
{ get command id }
else if communicationState = commStGetCommandId then
begin
uartStatus := getSerialPortByte(var uartByte: uint8);
if uartStatus = 0 then
begin
commandId := uartByte;
checksum := checksum + uartByte;
communicationNextState := commStGetDataLength;
end;
end;
{ get data length }
else if communicationState = commStGetDataLength then
begin
uartStatus := getSerialPortByte(var uartByte: uint8);
if uartStatus = 0 then
begin
dataLength := uartByte;
checksum := checksum + uartByte;
dataCount := dataLength;
communicationNextState := commStGetData;
end;
end;
{ get data }
else if communicationState = commStGetData then
begin
uartStatus := getSerialPortByte(var uartByte: uint8);
if uartStatus = 0 then
begin
data1 := data2;
data2 := data3;
data3 := data4;
data4 := uartByte;
checksum := checksum + uartByte;
dataCount := dataCount-1;
if dataCount = 0 then
communicationNextState := commStGetChecksum;
end;
end;
{ get checksum }
else if communicationState = commStGetChecksum then
begin
uartStatus := getSerialPortByte(var uartByte: uint8);
if uartStatus = 0 then
begin
if uartByte = checksum then
communicationState := commStExecuteCommand;
else
begin
commandId := commandNack;
dataLength := 0;
communicationNextState := commStSendHeader;
end;
end;
end;
{ execute command }
else if communicationState = commStExecuteCommand then
begin
if (commandId = commandWriteMem) and (dataLength = commandWriteLength) then
begin
memAddress := data1 + (data2 shl 8);
memData := data3 + (data4 shl 8);
mem[memAddress] := memData;
dataLength := 0;
communicationNextState := commStSendHeader;
end;
else if (commandId = commandReadMem) and (dataLength = commandReadLength) then
begin
memAddress := data3 + (data4 shl 8);
memData := mem[memAddress];
dataLength := 2;
data1 := memData and $00FF;
data2 := memData shr 8;
communicationNextState := commStSendHeader;
end;
else
begin
commandId := commandNack;
dataLength := 0;
communicationNextState := commStSendHeader;
end;
end;
{ send header }
else if communicationState = commStSendHeader then
begin
uartByte := commandHeader;
uartStatus := sendSerialPort(var uartByte: uint8);
if uartStatus = 0 then
begin
checksum := uartByte;
communicationNextState := commStSendPacketId;
end;
end;
{ send packet id }
else if communicationState = commStSendPacketId then
begin
uartByte := packetId;
uartStatus := sendSerialPort(var uartByte: uint8);
if uartStatus = 0 then
begin
checksum := checksum + uartByte;
communicationNextState := commStSendCommandId;
end;
end;
{ send command id }
else if communicationState = commStSendCommandId then
begin
uartByte := commandId;
uartStatus := sendSerialPort(var uartByte: uint8);
if uartStatus = 0 then
begin
checksum := checksum + uartByte;
communicationNextState := commStSendDataLength;
end;
end;
{ send data length }
else if communicationState = commStSendDataLength then
begin
uartByte := dataLength;
dataCount := dataLength;
uartStatus := sendSerialPort(var uartByte: uint8);
if uartStatus = 0 then
begin
checksum := checksum + uartByte;
communicationNextState := commStSendData;
end;
end;
{ send data }
else if communicationState = commStSendData then
begin
if dataCount > 0 then
begin
uartByte := data1;
data2 := data1;
data3 := data2;
data4 := data3;
uartStatus := sendSerialPort(var uartByte: uint8);
if uartStatus = 0 then
begin
checksum := checksum + uartByte;
dataCount := dataCount-1;
end;
end;
else
communicationNextState := commStSendChecksum;
end;
{ send checksum }
else if communicationState = commStSendChecksum then
begin
uartByte := checksum and $00FF;
uartStatus := sendSerialPort(var uartByte: uint8);
if uartStatus = 0 then
communicationNextState := commStIdle;
end;
{ update state }
communicationState := communicationNextState;
end;
{==============================================================================}
{ Main program }
{==============================================================================}
begin
{ initialize SoC registers }
initRegisters;
{ initialize communication state machine }
communicationState := commStIdle;
{ main loop }
while true do begin
{ update communication state machine }
updateStateMachine(var communicationState : word; var uartByte : uint8);
{ check for timeout }
end;
end.