Skip to content
Snippets Groups Projects
Commit cd3527cd authored by RobertPatzke's avatar RobertPatzke
Browse files

Update 20220329

parent a59d92a6
Branches
No related tags found
No related merge requests found
//-----------------------------------------------------------------------------
// Thema: Social Manufacturing Network / Development Environment
// Datei: ComRingBuf.cpp
// Editor: Robert Patzke
// URI/URL: www.mfp-portal.de
//-----------------------------------------------------------------------------
// Lizenz: CC-BY-SA (wikipedia: Creative Commons)
// Datum: 21. November 2021
//
// Der Inhalt dieser Datei sind Festlegungen zur Gestaltung eines Ringpuffers.
//
#include "ComRingBuf.h"
// --------------------------------------------------------------------------
// Initialisierungen
// --------------------------------------------------------------------------
ComRingBuf::ComRingBuf()
{
rbReadIdx = 0;
rbWriteIdx = 0;
sbReadIdx = 0;
sbWriteIdx = 0;
newLineMode = NewLineModeNL;
}
void ComRingBuf::begin(IntrfSerial *ser)
{
serIf = ser;
}
// --------------------------------------------------------------------------
// Konfiguration
// --------------------------------------------------------------------------
//
void ComRingBuf::setNewLineMode(byte nlMode)
{
newLineMode = nlMode;
}
// --------------------------------------------------------------------------
// Schnittstellen
// --------------------------------------------------------------------------
//
// Byte aus dem Sendepuffer lesen
//
bool ComRingBuf::getByteSnd(byte *dest)
{
if(sbReadIdx == sbWriteIdx) return(false);
*dest = sndBuffer[sbReadIdx];
sbReadIdx++;
if(sbReadIdx >= sbSize)
sbReadIdx = 0;
return(true);
}
// Byte in den Empfangspuffer schreiben
//
void ComRingBuf::putByteRec(byte b)
{
int space = rbReadIdx - rbWriteIdx - 1;
if(space == 0) return;
}
// ----------------------------------------------------------------------------
// Writing and reading data via circular buffer (default usage)
// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------
// Lesen (Empfangsvorgänge)
// ----------------------------------------------------------------------------
void ComRingBuf::setReadBuffer(int size, byte *bufPtr)
{
recBuffer = bufPtr;
rbSize = size;
rbReadIdx = 0;
rbWriteIdx = 0;
}
int ComRingBuf::getChr()
{
int retv;
if(rbReadIdx == rbWriteIdx)
return(EOF);
retv = recBuffer[rbReadIdx];
rbReadIdx++;
if(rbReadIdx >= rbSize)
rbReadIdx = 0;
return(retv);
}
void ComRingBuf::clrRecBuf()
{
rbReadIdx = 0;
rbWriteIdx = 0;
}
int ComRingBuf::getAll(byte *buffer)
{
int count, i;
int tmpInt;
if(rbReadIdx == rbWriteIdx)
return(EOF);
tmpInt = rbWriteIdx - rbReadIdx;
if(tmpInt < 0)
count = tmpInt + rbSize;
else
count = tmpInt;
for(i = 0; i < count; i++)
{
buffer[i] = recBuffer[rbReadIdx];
rbReadIdx++;
if(rbReadIdx >= rbSize)
rbReadIdx = 0;
}
return(count);
}
int ComRingBuf::getCount(int len, byte *buffer)
{
int count, i;
int tmpInt;
if(rbReadIdx == rbWriteIdx)
return(0);
tmpInt = rbWriteIdx - rbReadIdx;
if(tmpInt < 0)
count = tmpInt + rbSize;
else
count = tmpInt;
if(len > count)
len = count;
for(i = 0; i < len; i++)
{
buffer[i] = recBuffer[rbReadIdx];
rbReadIdx++;
if(rbReadIdx >= rbSize)
rbReadIdx = 0;
}
return(len);
}
int ComRingBuf::getCountStr(int len, char *buffer)
{
int nrChar;
nrChar = getCount(len, (uint8_t *) buffer);
if(nrChar == EOF) return(EOF);
buffer[nrChar] = 0;
return(nrChar);
}
int ComRingBuf::getLine(char *buffer)
{
bool eol;
int count, i;
int tmpInt;
if(rbReadIdx == rbWriteIdx)
return(0);
tmpInt = rbWriteIdx - rbReadIdx;
if(tmpInt < 0)
count = tmpInt + rbSize;
else
count = tmpInt;
eol = false;
for(i = 0; i < count; i++)
{
buffer[i] = recBuffer[rbReadIdx];
if(!eol)
{
if(buffer[i] == '\r' || buffer[i] == '\n')
eol = true;
}
else
{
if(buffer[i] != '\r' && buffer[i] != '\n')
break;
}
rbReadIdx++;
if(rbReadIdx >= rbSize)
rbReadIdx = 0;
}
if(!eol) return(0);
buffer[i] = 0;
return(i);
}
int ComRingBuf::getLineDec(int *intValue)
{
bool eol, inVal;
int count, i, j;
int tmpInt;
char c;
char buffer[32];
if(rbReadIdx == rbWriteIdx)
return(0);
tmpInt = rbWriteIdx - rbReadIdx;
if(tmpInt < 0)
count = tmpInt + rbSize;
else
count = tmpInt;
if(count > 30)
count = 30;
eol = false;
j = 0;
inVal = false;
for(i = 0; i < count; i++)
{
c = recBuffer[rbReadIdx];
if(!inVal)
{
if(c > '9')
{
rbReadIdx++;
if(rbReadIdx >= rbSize)
rbReadIdx = 0;
continue;
}
inVal = true;
}
if(!eol)
{
if(c == '\r' || c == '\n')
eol = true;
}
else
{
if(c != '\r' && c != '\n')
break;
}
rbReadIdx++;
if(rbReadIdx >= rbSize)
rbReadIdx = 0;
buffer[j++] = c;
}
if(!eol) return(0);
buffer[j] = 0;
*intValue = atoi(buffer);
return(i);
}
char ComRingBuf::getC()
{
char retC;
if(rbReadIdx == rbWriteIdx)
return(0);
retC = recBuffer[rbReadIdx];
rbReadIdx++;
if(rbReadIdx >= rbSize)
rbReadIdx = 0;
return(retC);
}
int ComRingBuf::waitLine(int waitLoop, char *buffer)
{
char inChar;
bool eol;
if(loopCount == 0)
{
tmpIdx = 0;
}
tmpVal = inCount();
if(tmpVal < 1)
{
loopCount++;
if(loopCount < waitLoop)
return(0);
else
{
loopCount = 0;
return(EOF);
}
}
eol = false;
for(int i = 0; i < tmpVal; i++)
{
inChar = getC();
buffer[tmpIdx++] = inChar;
if(inChar == '\r' || inChar == '\n')
{
eol = true;
break;
}
}
if(eol)
{
buffer[tmpIdx] = 0;
loopCount = 0;
return(tmpIdx);
}
return(0);
}
//int ComRingBuf::waitLineDec(int waitLoop, int *intValue)
//{
//};
int ComRingBuf::chkLine(char *rsp)
{
int i,chkVal;
char chkChar;
chkVal = inCount();
if(chkVal <= strlen(rsp))
return(0);
chkVal = 0;
for(i = 0; i < strlen(rsp); i++)
{
chkChar = getC();
if(rsp[i] != chkChar)
{
chkVal = -100000;
break;
}
else
chkVal++;
}
if(chkVal < 0) chkVal = EOF;
while( (recBuffer[rbReadIdx] == '\r' || recBuffer[rbReadIdx] == '\n' )
&& (rbReadIdx != rbWriteIdx))
{
rbReadIdx++;
if(rbReadIdx >= rbSize)
rbReadIdx = 0;
}
return(chkVal);
}
int ComRingBuf::chkBuf(char *rsp)
{
int i,chkVal;
char chkChar;
chkVal = inCount();
if(chkVal < strlen(rsp))
return(0);
chkVal = 0;
for(i = 0; i < strlen(rsp); i++)
{
chkChar = getC();
if(rsp[i] != chkChar)
chkVal = -100;
else
chkVal++;
}
return(chkVal);
}
int ComRingBuf::waitAll(int waitLoop, byte *buffer)
{
}
int ComRingBuf::waitChkBuf(int waitLoop, char *rsp)
{
int i;
int chkVal;
char chkChar;
if(loopCount == 0)
{
tmpVal = strlen(rsp);
}
chkVal = inCount();
if(chkVal < tmpVal)
{
loopCount++;
if(loopCount < waitLoop)
return(0);
else
{
loopCount = 0;
return(-10);
}
}
chkChar = getC();
if(rsp[0] != chkChar)
return(0);
if(tmpVal == 1)
{
loopCount = 0;
return(1);
}
chkVal = 1;
for(i = 1; i < tmpVal; i++)
{
chkChar = getC();
if(rsp[i] != chkChar)
return(0);
else
chkVal++;
}
loopCount = 0;
return(chkVal);
}
int ComRingBuf::inCount(void)
{
int count = rbWriteIdx - rbReadIdx;
if(count < 0)
count += rbSize;
return(count);
}
int ComRingBuf::getRestChar(byte tagChr, int len, byte *buffer)
{
int count, i, j;
byte inChr;
int tmpInt;
bool tagged;
if(rbReadIdx == rbWriteIdx)
return(0);
tmpInt = rbWriteIdx - rbReadIdx;
if(tmpInt < 0)
count = tmpInt + rbSize;
else
count = tmpInt;
if(len > count)
len = count;
tagged = false;
j = 0;
for(i = 0; i < len; i++)
{
inChr = recBuffer[rbReadIdx];
rbReadIdx++;
if(rbReadIdx >= rbSize)
rbReadIdx = 0;
if(!tagged)
{
if(inChr != tagChr)
continue;
tagged = true;
continue;
}
buffer[j++] = inChr;
}
if(!tagged) j = -1;
return(j);
}
int ComRingBuf::getRestStr(char *tagStr, int len, byte *buffer)
{
int count, i, j, tmpIdx;
byte inChr;
int tmpInt;
bool tagged;
int tagLen;
int tagIdx;
if(rbReadIdx == rbWriteIdx)
return(0);
tmpIdx = rbReadIdx;
tmpInt = rbWriteIdx - tmpIdx;
if(tmpInt < 0)
count = tmpInt + rbSize;
else
count = tmpInt;
if(len > count)
len = count;
tagged = false;
j = 0;
tagLen = (int) strlen(tagStr);
tagIdx = 0;
if(len < tagLen)
return(0);
for(i = 0; i < len; i++)
{
inChr = recBuffer[tmpIdx];
tmpIdx++;
if(tmpIdx >= rbSize)
tmpIdx = 0;
if(!tagged)
{
if(inChr != tagStr[tagIdx])
{
tagIdx = 0;
continue;
}
tagIdx++;
if(tagIdx == tagLen)
tagged = true;
continue;
}
buffer[j++] = inChr;
}
if(!tagged) return(EOF);
else
{
rbReadIdx = tmpIdx;
return(j);
}
}
int ComRingBuf::reqChkLine(char *req, char *rsp)
{
int i;
int chkVal;
char chkChar;
switch(reqChkState)
{
case 0:
rbReadIdx = 0;
rbWriteIdx = 0;
chkVal = putLine(req);
if(chkVal <= 0)
return(EOF);
tmpVal = strlen(rsp);
reqChkState = 1;
return(0);
case 1:
chkVal = inCount();
if(chkVal <= tmpVal)
return(0);
chkVal = 0;
for(i = 0; i < tmpVal; i++)
{
chkChar = getC();
if(rsp[i] != chkChar)
chkVal = -100;
else
chkVal++;
}
while( (recBuffer[rbReadIdx] == '\r' || recBuffer[rbReadIdx] == '\n')
&& (rbReadIdx != rbWriteIdx) )
{
rbReadIdx++;
if(rbReadIdx >= rbSize)
rbReadIdx = 0;
}
reqChkState = 0;
return(chkVal);
}
return(-1000); // internal error with <reqChkState>
}
// ----------------------------------------------------------------------------
// Schreiben (Sendevorgänge)
// ----------------------------------------------------------------------------
void ComRingBuf::setWriteBuffer(int size, byte *bufPtr)
{
sndBuffer = bufPtr;
sbSize = size;
sbReadIdx = 0;
sbWriteIdx = 0;
}
int ComRingBuf::putChr(int chr)
{
int space;
bool txDone;
if(sndBuffer == NULL) return(EOF);
if(serIf == NULL) return(EOF);
space = getSpace();
if(space == 0)
{
// Wenn der Sendepuffer voll ist, dann kann der Entlader feststecken
serIf->resuSend();
return(EOF);
}
if(sbReadIdx == sbWriteIdx)
{
// Wenn der Sendepuffer leer ist, dann kann das Zeichen evt.
// direkt gesendet werden.
txDone = serIf->condSend(chr);
if(txDone) return(chr);
}
putBufB(chr);
return(chr);
}
int ComRingBuf::putStr(char *msg)
{
int sIdx = 0;
if(sndBuffer == NULL) return(EOF);
if(serIf == NULL) return(EOF);
int space = getSpace();
int len = strlen(msg);
if(space < len)
{
serIf->resuSend();
return(EOF);
}
if(sbReadIdx == sbWriteIdx)
{
// Wenn der Sendepuffer leer ist, dann kann das erste Zeichen evt.
// direkt gesendet werden.
if(serIf->condSend(msg[0]))
sIdx = 1;
}
for (int i = sIdx; i < len; i++)
{
sndBuffer[sbWriteIdx] = msg[i];
sbWriteIdx++;
if(sbWriteIdx >= sbSize)
sbWriteIdx = 0;
}
return(len);
}
int ComRingBuf::putSeq(byte *msg, int n)
{
int sIdx = 0;
if(sndBuffer == NULL) return(EOF);
if(serIf == NULL) return(EOF);
int space = getSpace();
if(space < n)
{
serIf->resuSend();
return(EOF);
}
if(sbReadIdx == sbWriteIdx)
{
// Wenn der Sendepuffer leer ist, dann kann das erste Zeichen evt.
// direkt gesendet werden.
if(serIf->condSend(msg[0]))
sIdx = 1;
}
for (int i = sIdx; i < n; i++)
{
sndBuffer[sbWriteIdx] = msg[i];
sbWriteIdx++;
if(sbWriteIdx >= sbSize)
sbWriteIdx = 0;
}
return(n);
}
int ComRingBuf::putNL()
{
int retv = 0;
if(newLineMode & NewLineModeCR)
{
putBufB('\r');
retv++;
}
if(newLineMode & NewLineModeNL)
{
putBufB('\n');
retv++;
}
return(retv);
}
int ComRingBuf::putLine(char *msg)
{
int retv, nl;
retv = putStr(msg);
if(retv < 0)
return(retv);
nl = putNL();
return(retv);
}
//int ComRingBuf::putLine(char *msg, char c)
//{
//}
//int ComRingBuf::putLine(char *msg, int n)
//{
//}
// --------------------------------------------------------------------------
// Debugging
// --------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
// Thema: Social Manufacturing Network / Development Environment
// Datei: ComRingBuf.h
// Editor: Robert Patzke
// URI/URL: www.mfp-portal.de
//-----------------------------------------------------------------------------
// Lizenz: CC-BY-SA (wikipedia: Creative Commons)
// Datum: 21. November 2021
//
// Der Inhalt dieser Datei sind Festlegungen zur Gestaltung eines Ringpuffers.
//
#ifndef ComRingBuf_h
#define ComRingBuf_h
// ----------------------------------------------------------------------------
#include "stddef.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "arduinoDefs.h"
#include "IntrfBuf.h"
#include "IntrfSerial.h"
#define NewLineModeCR 0x01
#define NewLineModeNL 0x02
// ----------------------------------------------------------------------------
// C o m R i n g B u f
// ----------------------------------------------------------------------------
class ComRingBuf : IntrfBuf
{
private:
// --------------------------------------------------------------------------
// Lokale Daten
// --------------------------------------------------------------------------
//
// Zugang zur Peripherie
//
IntrfSerial *serIf;
// Lesen und Schreiben von Zeichen (Bytes)
//
byte *ptrSend; // Der (veraenderliche) Sendezeiger
byte *ptrRec; // Der (veraenderliche) Empfangszeiger
int maxRec; // Maximale Anzahl zu empfangender Bytes
byte endChrRec; // Abschlusszeichen beim Empfang
byte condMaskCom; // Bedingungen fuer den Datenaustausch
byte newLineMode; // Art für eine neue Zeile (CR/LF)
byte *recBuffer; // Receive ring buffer start address
word rbReadIdx; // Read index
word rbWriteIdx; // Write index
word rbSize; // Buffer size
byte *sndBuffer; // Transmit ring buffer start address
word sbReadIdx; // Read index
word sbWriteIdx; // Write index
word sbSize; // Buffer size
int loopCount; // For internal time out checking
int reqChkState; // State of request/check procedure
int tmpVal; // Variable for temporary data storage
int tmpIdx; // Variable for temporary array index
// --------------------------------------------------------------------------
// Lokale Funktionen
// --------------------------------------------------------------------------
//
char getC();
int putNL();
// --------------------------------------------------------------------------
// Inline-Funktionen
// --------------------------------------------------------------------------
//
void putBufB(byte b)
{
sndBuffer[sbWriteIdx] = b;
sbWriteIdx++;
if(sbWriteIdx >= sbSize)
sbWriteIdx = 0;
}
int getSpace()
{
int space = sbReadIdx - sbWriteIdx - 1;
if(space < 0) space += sbSize;
return(space);
}
public:
// --------------------------------------------------------------------------
// Initialisierungen
// --------------------------------------------------------------------------
ComRingBuf();
void begin(IntrfSerial *ser);
// --------------------------------------------------------------------------
// Konfiguration
// --------------------------------------------------------------------------
//
void setNewLineMode(byte nlMode);
// --------------------------------------------------------------------------
// Schnittstellen
// --------------------------------------------------------------------------
//
bool getByteSnd(byte *dest);
void putByteRec(byte b); // Byte vom Empfang an Puffer geben
// Zuweisen eines Speichers (*bufPtr) der Größe size für den Lesepuffer
//
void setReadBuffer(int size, byte *bufPtr);
// --------------------------------------------------------------------------
// Steuerung
// --------------------------------------------------------------------------
//
// ----------------------------------------------
// Ein einzelnes Zeichen aus dem Ringpuffer lesen
// ----------------------------------------------
// Rückgabe EOF (-1), wenn kein Zeichen vorhanden
// sonst das älteste Zeichen aus dem Ringpuffer
//
int getChr();
// ----------------------------------------------
// Löschen des Emmpfangspuffers
// ----------------------------------------------
//
void clrRecBuf();
// --------------------------------------------------
// Alle empfangenen Zeichen aus dem Ringpuffer lesen
// --------------------------------------------------
// Rückgabe EOF (-1), wenn kein Zeichen vorhanden
// sonst die Anzahl der empfangenen Zeichen
//
int getAll(byte *buffer);
// ----------------------------------------------------------
// Begrenzte Anzahl empfangener Zeichen aus Ringpuffer lesen
// ----------------------------------------------------------
// Rückgabe EOF (-1), wenn kein Zeichen vorhanden
// sonst die Anzahl der ausgelesenen Zeichen
//
int getCount(int count, byte *buffer);
// ------------------------------------------------------------------------
// Begrenzte Anzahl Zeichen als 0-terminierten String aus Ringpuffer lesen
// ------------------------------------------------------------------------
// Rückgabe EOF (-1), wenn kein Zeichen vorhanden
// sonst die Anzahl der ausgelesenen Zeichen
//
int getCountStr(int count, char *buffer);
// ---------------------------------------------------------
// Die nächste Zeile (Zeichen bis CR und/oder LF) als String
// ---------------------------------------------------------
// Rückgabe EOF (-1), wenn kein Zeichen vorhanden
// sonst die Anzahl der ausgelesenen Zeichen
//
int getLine(char *buffer);
// -----------------------------------------------
// Die nächste im Puffer enthaltene Zeile auslesen
// und die darin enthaltene Dezimalzahl übergeben
// -----------------------------------------------
// Rückgabe EOF (-1), wenn kein Zeichen vorhanden
// sonst die Anzahl der ausgelesenen Zeichen
// oder 0, wenn keine Dezimalzahl enthalten war
//
int getLineDec(int *intValue);
// ---------------------------------------------------------
// Warten auf Zeile (Zeichen bis CR und/oder LF) als String
// ---------------------------------------------------------
// Rückgabe EOF (-1), wenn Wartezyklen verstrichen
// Rückgabe 0, solange kein Zeilenende gelesen
// sonst die Anzahl der ausgelesenen Zeichen
//
int waitLine(int waitLoop, char *buffer);
//int waitLineDec(int waitLoop, int *intValue);
// ---------------------------------------------------------
// Testen der Zeile im Puffer
// ---------------------------------------------------------
// Rückgabe 0, wenn Teststring (noch) nicht enthalten
// sonst die Länge des Teststring
// EOF, wenn Zeile im Puffer (gelöscht) nicht passte
//
int chkLine(char *rsp);
int chkBuf(char *rsp);
int waitAll(int waitLoop, byte *buffer);
int waitChkBuf(int waitLoop, char *rsp);
int inCount(void);
int getRestChar(byte tagChr, int len, byte *buffer);
int getRestStr(char *tagStr, int len, byte *buffer);
int reqChkLine(char *req, char *rsp);
void setWriteBuffer(int size, byte *bufPtr);
int putChr(int chr);
int putStr(char *msg);
int putSeq(byte *msg, int n);
int putLine(char *msg);
//int putLine(char *msg, char c);
//int putLine(char *msg, int n);
// --------------------------------------------------------------------------
// Debugging
// --------------------------------------------------------------------------
//
};
// ----------------------------------------------------------------------------
#endif // beacon_h
//-----------------------------------------------------------------------------
// Thema: Steuerung optischer und akustischer Ausgaben für Perfomer
// Datei: SoaapMsg.h
// Editor: Robert Patzke
// URI/URL: www.hs-hannover.de
//-----------------------------------------------------------------------------
// Lizenz: CC-BY-SA (wikipedia: Creative Commons)
// Datum: 18. März 2022
//
// Diese Bibliothek (Klassse) enthält diverse Ressourcen zur Generierung
// von Meldungen und Telegrammen, die im Rahmen des SOAAP-Projektes
// eingesetzt werden.
//
#include "SoaapMsg.h"
// ----------------------------------------------------------------------------
// Konstruktoren und Initialisierungen
// ----------------------------------------------------------------------------
//
SoaapMsg::SoaapMsg()
{
}
// ----------------------------------------------------------------------------
// Anwenderschnittstelle (Funktionen)
// ----------------------------------------------------------------------------
//
// Erstellen eines ASCII-Telegramms zum Übertragen der Messwerte
//
int SoaapMsg::getMsgA(int area, int slvNr, SoaapApId appId, char *dest, byte *meas)
{
int msgIdx = 0;
int measIdx;
int measLen;
byte measByte;
char measChar;
dest[msgIdx++] = (char) (area | 0x10);
dest[msgIdx++] = (char) (slvNr | 0x60);
dest[msgIdx++] = (char) (appId);
switch(appId)
{
case saiDefaultMeas:
measLen = 18;
break;
case saiMaximalMeas:
measLen = 26;
break;
}
for(measIdx = 0; measIdx < measLen; measIdx++)
{
measByte = meas[measIdx];
// Erst das niederwertige Nibble als Hex-Ascii eintragen
//
measChar = (measByte & 0x0F) | 0x30;
if (measChar > 0x39) measChar += 7;
dest[msgIdx++] = measChar;
// dann das höherwertige Nibble
//
measChar = (measByte >> 4) | 0x30;
if (measChar > 0x39) measChar += 7;
dest[msgIdx++] = measChar;
}
dest[msgIdx] = '\0';
return(msgIdx);
}
// Umwandeln eines Messwert aus ASCII-Telegramm in Integer
//
short SoaapMsg::asc2meas(byte *ascList)
{
unsigned short retv;
retv = getVal(ascList[0]);
retv += getVal(ascList[1]) << 4;
retv += getVal(ascList[2]) << 8;
retv += getVal(ascList[3]) << 12;
return((short) retv);
}
// Auflösung der Messwerte in Zeichen (Bytes)
//
int SoaapMsg::measRes(SoaapApId appId)
{
int retv = 0;
switch(appId)
{
case saiDefaultMeas:
retv = 4;
break;
case saiMaximalMeas:
retv = 4;
break;
}
return(retv);
}
// Anzahl der Messwerte im Telegramm
//
int SoaapMsg::measCnt(SoaapApId appId)
{
int retv = 0;
switch(appId)
{
case saiDefaultMeas:
retv = 9;
break;
case saiMaximalMeas:
retv = 13;
break;
}
return(retv);
}
//-----------------------------------------------------------------------------
// Thema: Steuerung optischer und akustischer Ausgaben für Perfomer
// Datei: SoaapMsg.h
// Editor: Robert Patzke
// URI/URL: www.hs-hannover.de
//-----------------------------------------------------------------------------
// Lizenz: CC-BY-SA (wikipedia: Creative Commons)
// Datum: 18. März 2022
//
// Diese Bibliothek (Klassse) enthält diverse Ressourcen zur Generierung
// von Meldungen und Telegrammen, die im Rahmen des SOAAP-Projektes
// eingesetzt werden.
//
#ifndef SoaapMsg_h
#define SoaapMsg_h
#ifndef byte
#define byte unsigned char
#endif
typedef enum
{
saiDefaultMeas = 0x68,
saiMaximalMeas = 0x69
} SoaapApId;
class SoaapMsg
{
public:
// --------------------------------------------------------------------------
// Konstruktoren und Initialisierungen
// --------------------------------------------------------------------------
//
SoaapMsg();
private:
// --------------------------------------------------------------------------
// lokale Variablen
// --------------------------------------------------------------------------
//
// --------------------------------------------------------------------------
// Inline-Methoden
// --------------------------------------------------------------------------
//
int getVal(char hexAsc)
{
if(hexAsc < 0x39) return(hexAsc - 0x30);
else return(hexAsc - 0x37);
}
public:
// --------------------------------------------------------------------------
// Anwenderschnittstelle (Funktionen)
// --------------------------------------------------------------------------
//
int getMsgA(int area, int slvNr, SoaapApId appId, char *dest, byte *meas);
// Erstellen eines ASCII-Telegramms zum Übertragen der Messwerte
short asc2meas(byte *ascList);
// Umwandeln eines Messwert aus ASCII-Telegramm in Integer
int measRes(SoaapApId appId);
// Auflösung der Messwerte in Zeichen (Bytes)
int measCnt(SoaapApId appId);
// Anzahl der Messwerte
};
#endif // SoaapMsg_h
//-----------------------------------------------------------------------------
// S O A A P
//-----------------------------------------------------------------------------
// Thema: Steuerung optischer und akust. Ausgaben für Performance-Künstler
// Testen der Software für Arduino Due (Vermittler/Konfigurator)
// Datei: SoaapTestSer.h
// Editor: Robert Patzke
// URI/URL: www.hs-hannover.de
//-----------------------------------------------------------------------------
// Lizenz: CC-BY-SA (siehe Wikipedia: Creative Commons)
//
#ifndef SoaapTestSer_h
#define SoaapTestSer_h
// ----------------------------------------------------------------------------
// Definieren der aktuellen Testumgebung
// ----------------------------------------------------------------------------
//#define TEST001
// Durchreichen der Mastertelegramme von Serial1 an Serial (Serial0)
#define TEST002
// Ermitteln der Messwerte und Anzeige (dezimal) in einer Zustandsmaschine
#if defined TEST002
#define rbSize 128
// Vorwärtsreferenzen für die Zusztandsmaschine
void showMeasInit();
void showMeasWaitMsg();
void showMeasHeader();
void showMeasValue();
void showMeasView();
#endif
#endif // SoaapTestSer_h
//-----------------------------------------------------------------------------
// S O A A P
//-----------------------------------------------------------------------------
// Thema: Steuerung optischer und akust. Ausgaben für Performance-Künstler
// Testen der Software für Arduino Due (Vermittler/Konfigurator)
// Datei: SoaapTestSer.ino
// Editor: Robert Patzke
// URI/URL: www.hs-hannover.de
//-----------------------------------------------------------------------------
// Lizenz: CC-BY-SA (siehe Wikipedia: Creative Commons)
//
#include "Arduino.h"
#include "SoaapTestSer.h"
#include "LoopCheck.h"
#if defined TEST002
#include "StateMachine.h"
#include "SoaapMsg.h"
#endif
LoopCheck lc;
// Hilfsmethoden zur Steuerung zeitlicher Abläufe
SoaapMsg soaMsg;
// Hilfsmethoden für Telegrammaufbau und -auswertung
#if defined TEST002
#define showMeasCycleTime 500
StateMachine showMeas(showMeasInit, NULL, showMeasCycleTime);
#endif
void setup() // **********************************************************
{
Serial.begin(115200);
Serial1.begin(115200);
}
byte tmpBuffer[256];
// Temporärer Zwischenpuffer für Zeichenfolgen
int nrBytesIn = 0; // Antahl aktuell empfangener Zeichen
int serInCount = 0; // Zähler für empfangene Zeichen
int serInIdx = 0; // Index für besonderes Zeichen
byte serInChar; // Einzelnes empfangenes Zeichen
int slaveAdr; // Adresse des Soaap-Slave
int slaveArea; // Quellennetzwerk-Info, Bereich, o.ä.
SoaapApId appId; // Anwendungskennung, Datentyp, o.ä.
#if defined TEST002
int measIdx; // Index für den aktuellen Messwert
short measList[13]; // Liste der Messwerte
int nrMeas; // Anzahl der Messwerte im Telegramm
int resMeas; // Auflösung der Messwerte in Zeichen
int viewDiv; // Teiler für Anzeigehäufigkeit
#endif
void loop() // **********************************************************
{ // **********************************************************
lc.begin(); // Unbedingt an den Anfang der Arduino-LOOP
// --------------------------------------------------------------------------
#ifdef TEST001
// Durchreichen der Mastertelegramme von Serial1 an Serial (Serial0)
// --------------------------------------------------------------------------
// In einer einfacheren Variante dieses Tests wurde auf eine Zählung der
// eingetroffenen Zeichen verzichtet. Es wurde aber festgestellt, dass bei
// der Ausgabe sporadisch Zeichen fehlten (Telegramm um 1 Zeichen verkürzt).
// Zur Analyse wurde die Zählung der eingetroffenen Zeichen eingeführt und
// die Anzahl vor dem Telegramm ausgegeben.
// Seitdem trat der Zeichenverlust nicht mehr auf, eine Erklärung wurde
// nicht gefunden
// Dieser Test könnte auch noch einmal mit den alternativen, auf Interrupt
// auch beim Senden basierenden, Klassen von Robert Patzke (MFP GmbH) durch-
// geführt werden. Das wurde aus Zeitgründen noch nicht gemacht, auch weil
// die Ausgabe des Telegramms für SOAAP weniger wichtig ist.
nrBytesIn = Serial1.available();
// Anzahl der über Serial1 eingetroffenen Bytes (Zeichen)
if(nrBytesIn > 0)
{
Serial1.readBytes(tmpBuffer, nrBytesIn);
for(int i = 0; i < nrBytebyte tmpBuffer[256];
// Zwischenpuffer für Zeichenfolgen
sIn; i++)
{
serInCount++;
char c = (char) tmpBuffer[i];
if(c < 0x20)
{
Serial.println();
Serial.print(serInCount);
serInCount = 0;
}
Serial.print(c);
}
}
#endif
#ifdef TEST002
if(lc.timerMicro(lcTimer0,showMeasCycleTime,0))
showMeas.run();
#endif
// --------------------------------------------------------------------------
lc.end(); // Unbedingt an das Ende der Arduino-LOOP
}
#ifdef TEST002
// ----------------------------------------------------------------------------
// Zustandsmaschine zur Messwertanzeige
// ----------------------------------------------------------------------------
//
// Initialisierungen für die Zustandsmaschine und Startmeldung
//
void showMeasInit()
{
Serial.println("Anzeige der Messwerte mehrerer Soaap-Module.");
showMeas.enter(showMeasWaitMsg);
// Beim nächsten Takt zum Zustand <showMeasWaitMsg>.
}
// Warten auf ein Soaap-Telegramm von Serial 1
//
void showMeasWaitMsg()
{
nrBytesIn = Serial1.available();
// Anzahl der über Serial1 eingetroffenen Bytes (Zeichen)
if(nrBytesIn < 1) return;
// Beim nächsten Takt wieder in diesen Zustand, wenn kein Zeichen da
for(serInIdx = 0; serInIdx < nrBytesIn; serInIdx++)
{ // Suchen nach Startzeichen
serInChar = Serial1.read();
if(serInChar < 0x20) break;
}
if(serInIdx == nrBytesIn) return;
// Beim nächsten Takt wieder in diesen Zustand, wenn Startzeichen nicht dabei
slaveArea = serInChar & 0x1F; // Bereich auskodieren
serInIdx = 0; // Index neu setzen für Inhaltszuordnung
showMeas.enter(showMeasHeader);
// Beim nächsten Takt zum Zustand <showMeasHeader>
}
// Warten auf den Telegrammkopf und auswerten
//
void showMeasHeader()
{
nrBytesIn = Serial1.available();
// Anzahl der über Serial1 eingetroffenen Bytes (Zeichen)
if(nrBytesIn < 1) return;
// Beim nächsten Takt wieder in diesen Zustand, wenn kein Zeichen da
serInChar = Serial1.read();
// einzelnes Zeichen lesen
if(serInIdx == 0) // nach der Area folgt die Slaveadresse
{
slaveAdr = serInChar & 0x1F; // 1 - 31
serInIdx++;
// Beim nächsten Takt wieder in diesen Zustand
}
else // und dann die Anwendungskennung
{
appId = (SoaapApId) serInChar;
measIdx = 0; // Index für Messwertunterscheidung
serInIdx = 0; // Index für Messwertaufbau
nrMeas = soaMsg.measCnt(appId); // Anzahl Messwerte im Telegramm
resMeas = soaMsg.measRes(appId); // Auflösung der Messwerte in Zeichen
showMeas.enter(showMeasValue);
// Beim nächsten Takt zum Zustand <showMeasValue>
}
}
// Warten auf Messwerte und Speichern
//
void showMeasValue()
{
int i;
do
{
nrBytesIn = Serial1.available();
// Anzahl der über Serial1 eingetroffenen Bytes (Zeichen)
if(nrBytesIn < 1) return;
// Beim nächsten Takt wieder in diesen Zustand, wenn kein Zeichen da
for(i = 0; i < nrBytesIn; i++)
{
tmpBuffer[serInIdx++] = Serial1.read();
// einzelnes Zeichen lesen
if(serInIdx == resMeas) break;
// Alle Zeichen vom Messwert da, also raus
}
if(serInIdx < resMeas) return;
// Wenn noch nicht ale Zeichen vom Messwert erfasst, dann von vorn
measList[measIdx++] = soaMsg.asc2meas(tmpBuffer);
// Zeichenkette in Messwert wandeln und speichern
if(measIdx == nrMeas) break;
// Falls mehr als ein Telegramm eingetroffen ist
// muss hier ein Ausstieg erfolgen
serInIdx = 0; // Nächste Zeichenfolge
}
while (Serial1.available() > 0);
// Die Taktzeit der Zustandsmaschine ist größer, als die
// Übertragungszeit von einem Zeichen.
// Deshalb werden in einem Zustandstakt alle inzwischen eingetroffenen
// Zeichen bearbeitet.
if(measIdx < nrMeas) return;
// Im Zustand bleiben, bis alle Messwerte gewandelt sind
viewDiv = 0; // Teiler für Anzeigehäufigkeit
showMeas.enter(showMeasView);
// Beim nächsten Takt zum Zustand <showMeasView>
}
// Anzeigen der Messwerte
//
void showMeasView()
{
if(viewDiv > 0) // Verzögern der Ausgabe über Zähler
{ // Ausgabe wird übersprungen und erst dann vorgenommen
viewDiv--; // wenn der Zähler auf 0 steht
showMeas.enter(showMeasWaitMsg); // neuen Messwert abwarten
return;
}
if(slaveAdr == 1)
{
for(int i = 0; i < 9; i++)
{
Serial.print(' ');
Serial.print(measList[i]); // Messwert anzeigen
}
Serial.println();
}
showMeas.enter(showMeasWaitMsg); // neuen Messwert abwarten
}
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment