{ mesa fpga UART 32 BIT } {I HM2LOW} const MesaUARTBaseAdd = $6000; { registers } MesaUARTRxTxStride = $10; MesaUARTRegStride = $04; MesaUARTTxData1 = $00; { 1 byte push } MesaUARTTxData2 = $04; { 2 byte push } MesaUARTTxData3 = $08; { 3 byte push } MesaUARTTxData4 = $0C; { 4 byte push } MesaUARTRxData1 = $400; { 1 byte pop } MesaUARTRxData2 = $404; { 2 byte pop } MesaUARTRxData3 = $408; { 3 byte pop } MesaUARTRxData4 = $40C; { 4 byte pop } MesaUARTTxFIFOCount = $100; MesaUARTTxMode = $300; MesaUARTRxFIFOCount = $500; MesaUARTRxMode = $700; { setup mode register map } MesaUARTTxBitRate = $200; MesaUARTRxBitRate = $600; MesaUARTBitRateMask= $FFFFF; { 20 bits } MesaUARTRxFIFOSize = 16; { bytes } MesaUARTTxFIFOSize = 16; { slots } MesaUARTNumUARTs = 8; MesaUARTFIFOMask = $1F; { bits } MesaUARTTxFIFOError = $0010; { fifo push overflow } MesaUARTTxDriveEnableAuto = $0020; MesaUARTDriveEnableBit = $0040; MesaUARTRxFalseStartBit = $0001; MesaUARTRxOverRun = $0002; MesaUARTRxMaskEnableBit = $0004; MesaUARTRxFIFOError = $0010; { read more than there } MesaUARTRxLostData = $0020; MesaUARTRxMask = $0040; MesaUARTRxFIFOHasData = $0080; var MesaUARTClock : longint; function BrAccumval(br,bm : real) : longint; var baud : real; begin baud := ((br*1048576.0)/MesaUARTClock)/bm; {writeln('MesaUARTClock ',MesaUARTClock); writeln('Braccum ',baud:10:3);} BrAccumval := trunc(baud); end; function RxCharsAvailable : integer; var ouraddress : word; begin ouraddress :=TheComport*MesaUartRegStride+MesaUARTBaseAdd+MesaUARTRxFIFOCount; RxCharsAvailable := Read32(ouraddress) and MesaUARTFIFOMask; end; function TxSlotsAvailable : integer; var ouraddress : word; begin ouraddress := TheComport*MesaUartRegStride+MesaUARTBaseAdd+MesaUARTTxFIFOCount; TxSlotsAvailable := MesaUARTTxFIFOSize - (Read32(ouraddress) and MesaUARTFIFOMask); end; procedure MesaSerTossChars(comport : word); begin Write32(comport*MesaUartRegStride+MesaUARTBaseAdd+MesaUARTRxFifoCount,0); end; procedure MesaUARTSetBitrate(comPort : word; bitrate : longint); begin Write32((comport*MesaUartRegStride)+MesaUARTBaseAdd+MesaUARTTxBitRate,bitrate); Write32((comport*MesaUartRegStride)+MesaUARTBaseAdd+MesaUARTRxBitRate,bitrate); end; procedure MesaUARTGetBitrate(comport : word; var bitrate : longint); begin bitrate := MesaUartBitrateMask and Read32((comport*MesaUartRegStride)+MesaUARTBaseAdd+MesaUARTTxBitRate); end; procedure MesaUARTSetBaud(comport : word;br,bm : real); begin MesaUARTSetBitrate(comport,BrAccumval(br,bm)); end; function MesaBaudRateValid(br,bm : real) : boolean; var ourbaud,testbaud,ratio : real; value : real; begin MesaBaudRateValid := true; ourbaud := br / bm; value := BrAccumval(br,bm); testbaud := MesaUARTClock * value / 65536.0; ratio := ourbaud / testbaud; if (ratio > 1.0) and (ratio > 1.03) then MesaBaudRateValid := false; if (ratio < 1.0) and (ratio < 0.97) then MesaBaudRateValid := false; end; function MesaSerRecvChar(var c : char) : boolean; var timeout : longint; ouraddress : word; begin timeout := CharTimeout; while ((RxCharsAvailable = 0) and (timeout<>0)) do timeout:=timeout-1; if timeout <> 0 then begin ouraddress := TheComport*MesaUartRxTxStride+MesaUARTBaseAdd+MesaUARTRxData1; c := char(Read32(ouraddress)); MesaSerRecvChar := true; end else MesaSerRecvChar := false; end; function MesaSerRecvString(n : integer;var s : string) : boolean; var count : integer; is : string; timeout : longint; begin timeout := CharTimeout; MesaSerRecvString := false; is := ''; while ((RxCharsAvailable < n) and (timeout<>0)) do timeout:=timeout-1; if timeout <> 0 then begin for count := 1 to n do begin is := is + char(Read32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTRxData1)); end; MesaSerRecvString := true; end else for count := 1 to n do is := is + 'E'; s := is; end; procedure MesaSerSendChar(c : char); begin while MesaUARTTxFIFOSize = Read32((TheComport*MesaUartRegStride)+MesaUARTBaseAdd+MesaUARTTxFIFOCount) do; Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData1,word(byte(c))); end; procedure MesaSnailSerSendChar(c : char); begin Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData1,word(byte(c))); end; procedure MesaSnailSendString(s : string); var index : byte; begin DisableInterrupts; for index := 1 to length(s) do begin MesaSnailSerSendChar(s[index]); end; EnableInterrupts; end; procedure FastMesaSendString(s : string); var len,index,lindex : integer; data : longint; longs,remains,rem : integer; begin DisableInterrupts; len := length(s); longs := len div 4; remains := len mod 4; index := 1; if remains <> 0 then rem := 1 else rem := 0; while TxSlotsAvailable < longs+rem do; for lindex := 1 to longs do begin LongIntByteRec(data).Byte0 := byte(s[index+0]); LongIntByteRec(data).Byte1 := byte(s[index+1]); LongIntByteRec(data).Byte2 := byte(s[index+2]); LongIntByteRec(data).Byte3 := byte(s[index+3]); index := index + 4; Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData4,data); end; case remains of 3 : begin LongIntByteRec(data).Byte0 := byte(s[index+0]); LongIntByteRec(data).Byte1 := byte(s[index+1]); LongIntByteRec(data).Byte2 := byte(s[index+2]); Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData3,data); end; 2 : begin LongIntByteRec(data).Byte0 := byte(s[index+0]); LongIntByteRec(data).Byte1 := byte(s[index+1]); Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData2,data); end; 1 : begin LongIntByteRec(data).Byte0 := byte(s[index+0]); Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData1,data); end; end; EnableInterrupts; end; procedure SlowMesaSendString(s : string); var len,index,lindex : integer; data : longint; longs,remains : integer; begin DisableInterrupts; len := length(s); longs := len div 4; remains := len mod 4; index := 1; for lindex := 1 to longs do begin while TxSlotsAvailable = 0 do; LongIntByteRec(data).Byte0 := byte(s[index+0]); LongIntByteRec(data).Byte1 := byte(s[index+1]); LongIntByteRec(data).Byte2 := byte(s[index+2]); LongIntByteRec(data).Byte3 := byte(s[index+3]); index := index + 4; Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData4,data); end; while TxSlotsAvailable = 0 do; case remains of 3 : begin LongIntByteRec(data).Byte0 := byte(s[index+0]); LongIntByteRec(data).Byte1 := byte(s[index+1]); LongIntByteRec(data).Byte2 := byte(s[index+2]); Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData3,data); end; 2 : begin LongIntByteRec(data).Byte0 := byte(s[index+0]); LongIntByteRec(data).Byte1 := byte(s[index+1]); Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData2,data); end; 1 : begin LongIntByteRec(data).Byte0 := byte(s[index+0]); Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData1,data); end; end; EnableInterrupts; end; procedure MesaSendString(s : string); begin if length(s) > 64 then SlowMesaSendString(s) else FastMesaSendString(s); end; procedure oldMesaSendString(s : string); var len,i : integer; slots : word; data : word; begin DisableInterrupts; len := length(s); i := 1; while i < (len+1) do begin slots := TXSlotsAvailable; while (slots <> 0) and (i < (len+1)) do begin if len-i > 0 then begin WordRec(data).LowByte := byte(s[i]); i := i + 1; WordRec(data).HighByte := byte(s[i]); i := i + 1; Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData2,word(data)); slots := slots-1; end else begin WordRec(data).LowByte := byte(s[i]); i := i + 1; Write32((TheComport*MesaUartRxTxStride)+MesaUARTBaseAdd+MesaUARTTxData1,data); slots := slots-1; end; end; end; EnableInterrupts; end; function MesaComportThere(comport : word) : boolean; var data : longint; ok : boolean; index : word; begin ok := false; FillHM2Array; MesaUARTClock := Read32(HostMotClockLowOffset); ZeroMasks; MakeOutputMasks(UARTTXTag,comport); for index := 0 to MaxConns -1 do begin if OutputMasks[index] <> 0 then begin Write32($1100+index*4,OutputMasks[index]); { ddr } Write32($1200+index*4,OutputMasks[index]); { altsource } ok := true end; end; MesaComPortThere := ok; { check for uart present } end; procedure MesaSerOpen(TheComport : word; br,bm : real); begin Write32((TheComport*MesaUartRegStride)+MesaUARTBaseAdd+MesaUARTTxMode,MesaUARTDriveEnableBit + $0); { no delay } Write32((TheComport*MesaUartRegStride)+MesaUARTBaseAdd+MesaUARTTxFIFOCount,0); { clear Tx FIFO} MesaSerTossChars(TheComport); { make real sure there are no pending chars } MesaUARTSetBaud(TheComport,br,bm); Write32((TheComport*MesaUartRegStride)+MesaUARTBaseAdd+MesaUARTRxMode,$0000); { full duplex } end; function MesaCanRead(ms : integer) : boolean; var ctimeout : longint; begin if ms <> 0 then begin ctimeout := LoopsPermS * longint(ms); while ((RxCharsAvailable = 0) and (ctimeout <> 0)) do ctimeout := ctimeout -1; if ctimeout <> 0 then MesaCanRead := true else MesaCanRead := false; end else if (RxCharsAvailable <> 0) then MesaCanRead := true else MesaCanRead := false end;