<?xml version="1.0" encoding="utf-8"?>---
FUNCTION_BLOCK PiFaceCaD EXTENDS spi
VAR_OUTPUT
bySwitches: BYTE;
END_VAR
VAR
_byHardwareAddress: BYTE;
_byCurDisplayControl: BYTE;
_byCurEntryMode: BYTE;
_byCurAddress: BYTE;
END_VAR
VAR_TEMP
i: INT;
k: INT;
END_VAR
SUPER^();
CASE _iState OF
0:
IF SUPER^.init() THEN
_iState := 1;
END_IF
1:
write8(_byHardwareAddress, IOCON, 8); //enable hardware addressing
// Set GPIO Port A as inputs (switches)
write8(_byHardwareAddress, IODIRA, 255);
write8(_byHardwareAddress, GPPUA, 255);
// Set GPIO Port B as outputs (connected to HD44780)
write8(_byHardwareAddress, IODIRB, 0);
// enable interrupts
write8(_byHardwareAddress, GPINTENA, 255);
sleep_ns(DELAY_SETUP_0_NS);
write8(_byHardwareAddress, LCD_PORT, 3);
LCDPulseEnable();
sleep_ns(DELAY_SETUP_1_NS);
write8(_byHardwareAddress, LCD_PORT, 3);
LCDPulseEnable();
sleep_ns(DELAY_SETUP_2_NS);
write8(_byHardwareAddress, LCD_PORT, 3);
LCDPulseEnable();
write8(_byHardwareAddress, LCD_PORT, 2);
LCDPulseEnable();
LCDSendCommand(LCD_FUNCTIONSET OR LCD_4BITMODE OR LCD_2LINE OR LCD_5X8DOTS);
LCDSendCommand(LCD_DISPLAYCONTROL OR LCD_DISPLAYOFF OR LCD_CURSOROFF OR LCD_BLINKOFF);
Clear();
_byCurEntryMode := LCD_ENTRYLEFT OR LCD_ENTRYSHIFTDECREMENT;
LCDSendCommand(LCD_ENTRYMODESET OR _byCurEntryMode);
_byCurDisplayControl := LCD_DISPLAYON OR LCD_CURSORON OR LCD_BLINKON;
LCDSendCommand(LCD_DISPLAYCONTROL OR _byCurDisplayControl);
SetText('CODESYS ON', 'RASPBERRY PI');
_iState := 10;
END_CASE
METHOD Initialize: UDINT
VAR_INPUT
wModuleType: UINT;
dwInstance: UDINT;
pConnector: pointer;
END_VAR
VAR
pParam: pointer;
udiResult: UDINT;
END_VAR
SUPER^.Initialize(wModuleType, dwInstance, pConnector);
(*pParam := ConfigGetParameter(_pConnector, 1);
IF pParam <> 0 THEN
_byHardwareAddress := IoStandard.ConfigGetParameterValueByte(pParam, ADR(udiResult));
END_IF*)
METHOD BeforeWriteOutputs: INT
VAR
i: USINT;
END_VAR
SUPER^.BeforeWriteOutputs();
METHOD AfterReadInputs: INT
VAR
aby: ARRAY [..] OF ;
END_VAR
SUPER^.AfterReadInputs();
IF _iState = 10 THEN
bySwitches := NOT read8(_byHardwareAddress, SWITCH_PORT);
END_IF
METHOD read8: BYTE
VAR_INPUT
byHardwareAddress: subrangeSigned;
byPort: BYTE;
END_VAR
VAR
abyTxBuffer: ARRAY [..] OF ;
abyRxBuffer: ARRAY [..] OF ;
END_VAR
abyTxBuffer[0] := 16#40 + SHL(byHardwareAddress, 1) + 1; //SPI_READ_CMD;
abyTxBuffer[1] := byPort;
abyTxBuffer[2] := 16#FF;
IF transfer(pabyTxBuffer:=ADR(abyTxBuffer) , pabyRxBuffer:=ADR(abyRxBuffer) , udiLen:=3 , uiDelayus:=5 ) THEN
read8 := abyRxBuffer[2];
ELSE
_iState := 1000;
END_IF
METHOD write8: BOOL
VAR_INPUT
byHardwareAddress: subrangeSigned;
byPort: BYTE;
byValue: BYTE;
END_VAR
VAR
abyTxBuffer: ARRAY [..] OF ;
abyRxBuffer: ARRAY [..] OF ;
END_VAR
abyTxBuffer[0] := 16#40 + SHL(byHardwareAddress, 1); //SPI_WRITE_CMD;
abyTxBuffer[1] := byPort;
abyTxBuffer[2] := byValue;
write8 := transfer(pabyTxBuffer:=ADR(abyTxBuffer) , pabyRxBuffer:=ADR(abyRxBuffer) , udiLen:=3 , uiDelayus:=5 );
IF NOT write8 THEN
_iState := 1000;
END_IF
METHOD LCDPulseEnable:
LCDSetEnable(TRUE);
sleep_ns(DELAY_PULSE_NS);
LCDSetEnable(FALSE);
sleep_ns(DELAY_PULSE_NS);
METHOD LCDSendCommand:
VAR_INPUT
usiCommand: USINT;
END_VAR
LCDSetRs(FALSE);
LCDSendByte(usiCommand);
sleep_ns(DELAY_SETTLE_NS);
METHOD LCDSendByte:
VAR_INPUT
usi: USINT;
END_VAR
VAR
usiCurrentState: USINT;
usiNew: USINT;
END_VAR
// get current lcd port state and clear the data bits
usiCurrentState := read8(_byHardwareAddress, LCD_PORT) AND 16#F0;
// send first nibble (0bXXXX0000)
usiNew := usiCurrentState OR SHR(usi, 4);
write8(_byHardwareAddress, LCD_PORT, usiNew);
LCDPulseEnable();
// send second nibble (0b0000XXXX)
usiNew := usiCurrentState OR (usi AND 2#1111);
write8(_byHardwareAddress, LCD_PORT, usiNew);
LCDPulseEnable();
METHOD writeBit: BOOL
VAR_INPUT
byHardwareAddress: subrangeSigned;
byPort: BYTE;
byBit: subrangeSigned;
xValue: BOOL;
END_VAR
VAR
byValue: BYTE;
END_VAR
byValue := read8(byHardwareAddress, byPort);
IF xValue THEN
byValue := byValue OR SHL(USINT#1, byBit);
ELSE
byValue := byValue AND NOT SHL(USINT#1, byBit);
END_IF
writeBit := write8(byHardwareAddress, byPort, byValue);
METHOD LCDSetRs:
VAR_INPUT
x: BOOL;
END_VAR
writeBit(_byHardwareAddress, LCD_PORT, PIN_RS, x);
METHOD sleep_ns:
VAR_INPUT
udiNs: UDINT;
END_VAR
VAR
udi1: ULINT;
udi2: ULINT;
END_VAR
SysTimeGetNs(udi1);
REPEAT
SysTimeGetNs(udi2);
UNTIL udi2-udi1 >= udiNs
END_REPEAT
METHOD LCDSetEnable:
VAR_INPUT
x: BOOL;
END_VAR
writeBit(_byHardwareAddress, LCD_PORT, PIN_ENABLE, x);
METHOD Write:
VAR_INPUT
sText: string;
END_VAR
VAR
i: INT;
pby: pointer;
END_VAR
LCDSendCommand(LCD_SETDDRAMADDR OR _byCurAddress);
pby := ADR(sText);
FOR i:=0 TO len(sText)-1 DO
IF pby[i] = 10 THEN
SetCursor(0,1);
ELSE
LCDSendData(pby[i]);
_byCurAddress := _byCurAddress + 1;
END_IF
END_FOR
METHOD Clear:
LCDSendCommand(LCD_CLEARDISPLAY);
_byCurAddress := 0;
sleep_ns(DELAY_CLEAR_NS);
METHOD Home:
LCDSendCommand(LCD_RETURNHOME);
_byCurAddress := 0;
sleep_ns(DELAY_CLEAR_NS);
METHOD SetCursor:
VAR_INPUT
usiColumn: USINT;
usiRow: USINT;
END_VAR
usiColumn := MAX(0, MIN(usiColumn, (LCD_RAM_WIDTH / 2) - 1));
usiRow := MAX(0, MIN(usiRow, LCD_MAX_LINES - 1));
_byCurAddress := (usiColumn + ROW_OFFSETS[usiRow]) MOD LCD_RAM_WIDTH;
LCDSendCommand(LCD_SETDDRAMADDR OR _byCurAddress);
METHOD LCDSendData:
VAR_INPUT
data: USINT;
END_VAR
LCDSetRs(TRUE);
LCDSendByte(data);
sleep_ns(DELAY_SETTLE_NS);
METHOD MoveLeft:
LCDSendCommand(LCD_CURSORSHIFT OR LCD_DISPLAYMOVE OR LCD_MOVELEFT);
METHOD MoveRight:
LCDSendCommand(LCD_CURSORSHIFT OR LCD_DISPLAYMOVE OR LCD_MOVERIGHT);
METHOD SetText:
VAR_INPUT
sLine1: string;
sLine2: string;
END_VAR
SetCursor(0, 0);
Write(sLine1);
SetCursor(0, 1);
Write(sLine2);
METHOD WriteCustomBitmap:
VAR_INPUT
byLocation: subrangeSigned;
END_VAR
LCDSendCommand(LCD_SETDDRAMADDR OR _byCurAddress);
LCDSendData(byLocation);
_byCurAddress := _byCurAddress + 1;
METHOD DefineCustomBitmap:
VAR_INPUT
byLocation: subrangeSigned;
abyBitmap: ARRAY [..] OF ;
END_VAR
VAR
i: INT;
END_VAR
LCDSendCommand(LCD_SETCGRAMADDR OR SHL(byLocation, 3));
FOR i := 0 TO 7 DO
LCDSendData(abyBitmap[i]);
END_FOR
VAR_GLOBAL
IODIRA: USINT;
IODIRB: USINT;
IPOLA: USINT;
IPOLB: USINT;
GPINTENA: USINT;
GPINTENB: USINT;
DEFVALA: USINT;
DEFVALB: USINT;
INTCONA: USINT;
INTCONB: USINT;
IOCON: USINT;
GPPUA: USINT;
GPPUB: USINT;
INTFA: USINT;
INTFB: USINT;
INTCAPA: USINT;
INTCAPB: USINT;
GPIOA: USINT;
GPIOB: USINT;
OLATA: USINT;
OLATB: USINT;
BANK_OFF: USINT;
BANK_ON: USINT;
INT_MIRROR_ON: USINT;
INT_MIRROR_OFF: USINT;
SEQOP_OFF: USINT;
SEQOP_ON: USINT;
DISSLW_ON: USINT;
DISSLW_OFF: USINT;
HAEN_ON: USINT;
HAEN_OFF: USINT;
ODR_ON: USINT;
ODR_OFF: USINT;
INTPOL_HIGH: USINT;
INTPOL_LOW: USINT;
DELAY_PULSE_NS: UDINT;
DELAY_SETTLE_NS: UDINT;
DELAY_CLEAR_NS: UDINT;
DELAY_SETUP_0_NS: UDINT;
DELAY_SETUP_1_NS: UDINT;
DELAY_SETUP_2_NS: UDINT;
PIN_D4: USINT;
PIN_D5: USINT;
PIN_D6: USINT;
PIN_D7: USINT;
PIN_ENABLE: USINT;
PIN_RW: USINT;
PIN_RS: USINT;
PIN_BACKLIGHT: USINT;
LCD_CLEARDISPLAY: USINT;
LCD_RETURNHOME: USINT;
LCD_ENTRYMODESET: USINT;
LCD_DISPLAYCONTROL: USINT;
LCD_CURSORSHIFT: USINT;
LCD_FUNCTIONSET: USINT;
LCD_SETCGRAMADDR: USINT;
LCD_SETDDRAMADDR: USINT;
LCD_NEWLINE: USINT;
LCD_ENTRYRIGHT: USINT;
LCD_ENTRYLEFT: USINT;
LCD_ENTRYSHIFTINCREMENT: USINT;
LCD_ENTRYSHIFTDECREMENT: USINT;
LCD_DISPLAYON: USINT;
LCD_DISPLAYOFF: USINT;
LCD_CURSORON: USINT;
LCD_CURSOROFF: USINT;
LCD_BLINKON: USINT;
LCD_BLINKOFF: USINT;
LCD_DISPLAYMOVE: USINT;
LCD_CURSORMOVE: USINT;
LCD_MOVERIGHT: USINT;
LCD_MOVELEFT: USINT;
LCD_8BITMODE: USINT;
LCD_4BITMODE: USINT;
LCD_2LINE: USINT;
LCD_1LINE: USINT;
LCD_5X10DOTS: USINT;
LCD_5X8DOTS: USINT;
LCD_MAX_LINES: USINT;
LCD_WIDTH: USINT;
LCD_RAM_WIDTH: USINT;
ROW_OFFSETS: ARRAY [..] OF ;
SWITCH_PORT: USINT;
LCD_PORT: USINT;
END_VAR