1
0
SEm-Labos/06-07-08-09-SystemOnChip/SystemOnChip/hdl/beamer.pas
github-classroom[bot] d212040c30
Initial commit
2024-02-23 13:01:05 +00:00

316 lines
13 KiB
ObjectPascal

{
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;
commandHeader = $AA;
commandNack = $00;
commandWriteMem = $03;
commandReadMem = $04;
commandWriteLength = 4;
commandReadLength = 2;
beamerBaseAddress = $0020;
beamerCtlOffset = $0000;
beamerSpeedOffset = $0001;
beamerCtlInit = $0401;
beamerSpeedInit = $0004;
{==============================================================================}
{ Variables }
{==============================================================================}
var
packetId, commandId, errorId: uint8;
memoryAddress, memoryData: word;
{==============================================================================}
{ Procedures and functions }
{==============================================================================}
{============================================================================}
{ Register-level accesses }
{============================================================================}
{----------------------------------------------------------------------------}
{ Registers initializations }
{----------------------------------------------------------------------------}
procedure initRegisters;
begin
{ initialize GPIO }
mem[gpioBaseAddress+gpioDataOffset] := $AA;
mem[gpioBaseAddress+gpioEnableOffset] := $0F;
{ initialize UART }
mem[uartBaseAddress+uartBaudOffset] := uartBaudCount;
{ initialize beamer peripheral }
mem[beamerBaseAddress+beamerCtlOffset] := beamerCtlInit;
mem[beamerBaseAddress+beamerSpeedOffset] := beamerSpeedInit;
end;
{----------------------------------------------------------------------------}
{ Get byte from serial port }
{----------------------------------------------------------------------------}
procedure getSerialPortByte : uint8;
var
uartByte: uint8;
begin
{ poll until data byte available }
uartByte := 0;
while uartByte = 0 do
begin
{ spend time in order not to overcharge the AHB bus }
for index := 1 to uartpollDelay do
noOperation;
{ read status register }
uartByte := mem[uartBaseAddress+uartStatusOffset] and uartDataReady;
end;
{ read data register and return it }
getSerialPortByte := mem[uartBaseAddress];
end;
{----------------------------------------------------------------------------}
{ Send byte to serial port }
{----------------------------------------------------------------------------}
procedure sendSerialPort(uartByte : uint8);
var
statusByte: uint8;
begin
{ poll until ready to send }
statusByte := mem[uartBaseAddress+uartStatusOffset] and uartSending;
while statusByte = 0 do
begin
{ spend time in order not to overcharge the AHB bus }
for index := 1 to uartpollDelay do
noOperation;
{ read status register }
statusByte := mem[uartBaseAddress+uartStatusOffset] and uartSending;
end;
{ write data register }
mem[uartBaseAddress] := uartByte;
end;
{============================================================================}
{ Communication protocol }
{============================================================================}
{----------------------------------------------------------------------------}
{ Get command }
{----------------------------------------------------------------------------}
function getCommand(
var packetId, commandId, commandLength : uint8;
var memoryAddress, memoryData : word
) : uint8;
var
uartData: uint8;
checksum: word;
begin
{ wait for new command header }
uartData := 0;
while uartData <> commandHeader do
uartData := getSerialPortByte;
checksum := uartData;
{ get packet id }
packetId := getSerialPortByte;
checksum := checksum + packetId;
{ get command }
commandId := getSerialPortByte;
checksum := checksum + commandId;
{ process known commands }
if (commandId = commandWriteMem) or (commandId = commandReadMem) then
begin
{ get command length }
commandLength := getSerialPortByte;
checksum := checksum + commandLength;
{ check command lengths }
if (commandId = commandWriteMem) and (commandLength <> commandWriteLength) then
getCommand := 1;
else if (commandId = commandReadMem) and (commandLength <> commandReadLength) then
getCommand := 1;
else
begin
{ get address }
memoryAddress := getSerialPortByte;
checksum := checksum + memoryAddress;
memoryAddress := (memoryAddress shl 8) + getSerialPortByte;
checksum := checksum + memoryAddress;
{ get data }
if commandId = commandReadMem then
begin
memoryData := getSerialPortByte;
checksum := checksum + memoryData;
memoryData := (memoryData shl 8) + getSerialPortByte;
checksum := checksum + memoryData;
end;
{ get and verify checksum}
if getSerialPortByte = (checksum and $00FF) then
getCommand := 0;
else
getCommand := 1;
end;
end;
else
getCommand := 1;
end;
{----------------------------------------------------------------------------}
{ Send NACK }
{----------------------------------------------------------------------------}
function sendNegativeAcknowledge(packetId : uint8);
var
uartData: uint8;
checksum: word;
begin
{ send packet header }
uartData := $AA;
sendSerialPort(uartData);
checksum := uartData;
{ send packet id }
uartData := packetId;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send command id }
uartData := commandNack;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send packet length }
uartData := 0;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send checksum }
uartData := checksum and $00FF;
sendSerialPort(uartData);
end;
{----------------------------------------------------------------------------}
{ Send ACK }
{----------------------------------------------------------------------------}
function sendAcknowledge(packetId, commandId : uint8);
var
uartData: uint8;
checksum: word;
begin
{ send packet header }
uartData := $AA;
sendSerialPort(uartData);
checksum := uartData;
{ send packet id }
uartData := packetId;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send command id }
uartData := commandId;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send packet length }
uartData := 0;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send checksum }
uartData := checksum and $00FF;
sendSerialPort(uartData);
end;
{----------------------------------------------------------------------------}
{ Send READ_MEM reply }
{----------------------------------------------------------------------------}
function sendReadAnswer(packetId : uint8; memoryData: word);
var
uartData: uint8;
checksum: word;
begin
{ send packet header }
uartData := $AA;
sendSerialPort(uartData);
checksum := uartData;
{ send packet id }
uartData := packetId;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send command id }
uartData := commandReadMem;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send packet length }
uartData := 2;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send data low }
uartData := memoryData and $00FF;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send data high }
uartData := memoryData shr 8;
sendSerialPort(uartData);
checksum := checksum + uartData;
{ send checksum }
uartData := checksum and $00FF;
sendSerialPort(uartData);
end;
{==============================================================================}
{ Main program }
{==============================================================================}
begin
{ initialize SoC registers }
initRegisters;
{ main loop }
while true do begin
{ get a new command }
errorId := getCommand(packetId, commandId, memoryAddress, memoryData);
{ process command }
if errorId = 0 then
begin
{ process write command }
if commandId = commandWriteMem then
begin
mem[memoryAddress] := memoryData;
sendAcknowledge(packetId, commandId);
end;
{ process read command }
else if commandId = commandReadMem then
begin
memoryData := mem[memoryAddress];
sendReadAnswer(packetId, memoryData);
end;
{ reply to unknown command }
else
sendNegativeAcknowledge(packetId);
end;
{ negative acknowledge on reception error }
else
sendNegativeAcknowledge(packetId);
end;
end.
{
;---------------------------------------------------------------
; register definitions
; s0, s1: used for INPUT and OUTPUT operations
; S2: returns UART data byte
; S3: uart protocol checksum
; S4: uart protocol packet id
; S5: uart protocol command id
; S6: uart protocol address
; S7: uart protocol data
; S8: copy of UART data byte for debug
;---------------------------------------------------------------
}