From 27ddc7b30b00a0ef826f8f3801dbe8b8c02a2334 Mon Sep 17 00:00:00 2001 From: Neil McKechnie Date: Fri, 3 Feb 2023 12:56:19 +0000 Subject: [PATCH] IO_ExampleSerial - refactor and update comments To more directly reflect the bulk of HAL drivers, the .h/.cpp split has been removed and the class is fully defined in the .h file. --- IO_ExampleSerial.cpp | 129 ------------------------------------------- IO_ExampleSerial.h | 129 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 118 insertions(+), 140 deletions(-) delete mode 100644 IO_ExampleSerial.cpp diff --git a/IO_ExampleSerial.cpp b/IO_ExampleSerial.cpp deleted file mode 100644 index 12476db..0000000 --- a/IO_ExampleSerial.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * © 2021, Neil McKechnie. All rights reserved. - * - * This file is part of DCC++EX API - * - * This is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * It is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with CommandStation. If not, see . - */ - -#include -#include "IO_ExampleSerial.h" -#include "FSH.h" - -// Constructor -IO_ExampleSerial::IO_ExampleSerial(VPIN firstVpin, int nPins, HardwareSerial *serial, unsigned long baud) { - _firstVpin = firstVpin; - _nPins = nPins; - _pinValues = (uint16_t *)calloc(_nPins, sizeof(uint16_t)); - _baud = baud; - - // Save reference to serial port driver - _serial = serial; - - addDevice(this); -} - -// Static create method for one module. -void IO_ExampleSerial::create(VPIN firstVpin, int nPins, HardwareSerial *serial, unsigned long baud) { - if (checkNoOverlap(firstVpin,nPins)) new IO_ExampleSerial(firstVpin, nPins, serial, baud); -} - -// Device-specific initialisation -void IO_ExampleSerial::_begin() { - _serial->begin(_baud); -#if defined(DIAG_IO) - _display(); -#endif - - // Send a few # characters to the output - for (uint8_t i=0; i<3; i++) - _serial->write('#'); -} - -// Device-specific write function. Write a string in the form "#Wm,n#" -// where m is the vpin number, and n is the value. -void IO_ExampleSerial::_write(VPIN vpin, int value) { - int pin = vpin -_firstVpin; - #ifdef DIAG_IO - DIAG(F("IO_ExampleSerial::_write Pin:%d Value:%d"), (int)vpin, value); - #endif - // Send a command string over the serial line - _serial->print('#'); - _serial->print('W'); - _serial->print(pin); - _serial->print(','); - _serial->print(value); - _serial->println('#'); - DIAG(F("ExampleSerial Sent command, p1=%d, p2=%d"), vpin, value); - } - -// Device-specific read function. -int IO_ExampleSerial::_read(VPIN vpin) { - - // Return a value for the specified vpin. - int result = _pinValues[vpin-_firstVpin]; - - return result; -} - -// Loop function to do background scanning of the input port. State -// machine parses the incoming command as it is received. Command -// is in the form "#Nm,n#" where m is the index and n is the value. -void IO_ExampleSerial::_loop(unsigned long currentMicros) { - (void)currentMicros; // Suppress compiler warnings - if (_serial->available()) { - // Input data available to read. Read a character. - char c = _serial->read(); - switch (_inputState) { - case 0: // Waiting for start of command - if (c == '#') // Start of command received. - _inputState = 1; - break; - case 1: // Expecting command character - if (c == 'N') { // 'Notify' character received - _inputState = 2; - _inputValue = _inputIndex = 0; - } else - _inputState = 0; // Unexpected char, reset - break; - case 2: // reading first parameter (index) - if (isdigit(c)) - _inputIndex = _inputIndex * 10 + (c-'0'); - else if (c==',') - _inputState = 3; - else - _inputState = 0; // Unexpected char, reset - break; - case 3: // reading reading second parameter (value) - if (isdigit(c)) - _inputValue = _inputValue * 10 - (c-'0'); - else if (c=='#') { // End of command - // Complete command received, do something with it. - DIAG(F("ExampleSerial Received command, p1=%d, p2=%d"), _inputIndex, _inputValue); - if (_inputIndex < _nPins) { // Store value - _pinValues[_inputIndex] = _inputValue; - } - _inputState = 0; // Done, start again. - } else - _inputState = 0; // Unexpected char, reset - break; - } - } -} - -void IO_ExampleSerial::_display() { - DIAG(F("IO_ExampleSerial Configured on VPins:%d-%d"), (int)_firstVpin, - (int)_firstVpin+_nPins-1); -} - diff --git a/IO_ExampleSerial.h b/IO_ExampleSerial.h index 9b20399..da421c5 100644 --- a/IO_ExampleSerial.h +++ b/IO_ExampleSerial.h @@ -35,24 +35,131 @@ #include "IODevice.h" class IO_ExampleSerial : public IODevice { -public: - static void create(VPIN firstVpin, int nPins, HardwareSerial *serial, unsigned long baud); - -protected: - IO_ExampleSerial(VPIN firstVpin, int nPins, HardwareSerial *serial, unsigned long baud); - void _begin() override; - void _loop(unsigned long currentMicros) override; - void _write(VPIN vpin, int value) override; - int _read(VPIN vpin) override; - void _display() override; - private: + // Here we define the device-specific variables. HardwareSerial *_serial; uint8_t _inputState = 0; int _inputIndex = 0; int _inputValue = 0; uint16_t *_pinValues; // Pointer to block of memory containing pin values unsigned long _baud; + +public: + // Static function to handle "IO_ExampleSerial::create(...)" calls. + static void create(VPIN firstVpin, int nPins, HardwareSerial *serial, unsigned long baud) { + if (checkNoOverlap(firstVpin,nPins)) new IO_ExampleSerial(firstVpin, nPins, serial, baud); + } + +protected: + // Constructor. This should initialise variables etc. but not call other objects yet + // (e.g. Serial, I2CManager, and other parts of the CS functionality). + // defer those until the _begin() function. The 'addDevice' call is required unless + // the device is not to be added (e.g. because of incorrect parameters). + IO_ExampleSerial(VPIN firstVpin, int nPins, HardwareSerial *serial, unsigned long baud) { + _firstVpin = firstVpin; + _nPins = nPins; + _pinValues = (uint16_t *)calloc(_nPins, sizeof(uint16_t)); + _baud = baud; + + // Save reference to serial port driver + _serial = serial; + + addDevice(this); + } + + // Device-specific initialisation + void _begin() override { + _serial->begin(_baud); +#if defined(DIAG_IO) + _display(); +#endif + + // Send a few # characters to the output + for (uint8_t i=0; i<3; i++) + _serial->write('#'); + } + + // Device-specific write function. Write a string in the form "#Wm,n#" + // where m is the vpin number, and n is the value. + void _write(VPIN vpin, int value) { + int pin = vpin -_firstVpin; + #ifdef DIAG_IO + DIAG(F("IO_ExampleSerial::_write Pin:%d Value:%d"), (int)vpin, value); + #endif + // Send a command string over the serial line + _serial->print('#'); + _serial->print('W'); + _serial->print(pin); + _serial->print(','); + _serial->print(value); + _serial->println('#'); + DIAG(F("ExampleSerial Sent command, p1=%d, p2=%d"), vpin, value); + } + + // Device-specific read function. + int _read(VPIN vpin) { + + // Return a value for the specified vpin. + int result = _pinValues[vpin-_firstVpin]; + + return result; + } + + // Loop function to do background scanning of the input port. State + // machine parses the incoming command as it is received. Command + // is in the form "#Nm,n#" where m is the index and n is the value. + void _loop(unsigned long currentMicros) { + (void)currentMicros; // Suppress compiler warnings + if (_serial->available()) { + // Input data available to read. Read a character. + char c = _serial->read(); + switch (_inputState) { + case 0: // Waiting for start of command + if (c == '#') // Start of command received. + _inputState = 1; + break; + case 1: // Expecting command character + if (c == 'N') { // 'Notify' character received + _inputState = 2; + _inputValue = _inputIndex = 0; + } else + _inputState = 0; // Unexpected char, reset + break; + case 2: // reading first parameter (index) + if (isdigit(c)) + _inputIndex = _inputIndex * 10 + (c-'0'); + else if (c==',') + _inputState = 3; + else + _inputState = 0; // Unexpected char, reset + break; + case 3: // reading reading second parameter (value) + if (isdigit(c)) + _inputValue = _inputValue * 10 - (c-'0'); + else if (c=='#') { // End of command + // Complete command received, do something with it. + DIAG(F("ExampleSerial Received command, p1=%d, p2=%d"), _inputIndex, _inputValue); + if (_inputIndex >= 0 && _inputIndex < _nPins) { // Store value + _pinValues[_inputIndex] = _inputValue; + } + _inputState = 0; // Done, start again. + } else + _inputState = 0; // Unexpected char, reset + break; + } + } + } + + // Display information about the device, and perhaps its current condition (e.g. active, disabled etc). + // Here we display the current values held for the pins. + void _display() { + DIAG(F("IO_ExampleSerial Configured on VPins:%d-%d"), (int)_firstVpin, + (int)_firstVpin+_nPins-1); + for (int i=0; i<_nPins; i++) + DIAG(F(" VPin %2d: %d"), _firstVpin+i, _pinValues[i]); + } + + }; #endif // IO_EXAMPLESERIAL_H \ No newline at end of file