From 2a29d6713e3371cea22e857800c5d44494092ae3 Mon Sep 17 00:00:00 2001 From: hama Date: Thu, 16 Jun 2016 20:28:55 +0200 Subject: [PATCH] client: commands trace+getbuffer --- Server/client.cpp | 52 +++++++++++++++++++++++++++++++++++----- Server/cpidjinn.cpp | 5 ++-- Server/gpioprocessor.cpp | 35 +++++++++++++++++++++++++++ Server/gpioprocessor.hpp | 3 +++ Server/gpiotimer.cpp | 36 +++++++++++++++++++++++++++- Server/gpiotimer.hpp | 14 +++++++++++ 6 files changed, 136 insertions(+), 9 deletions(-) diff --git a/Server/client.cpp b/Server/client.cpp index 71e3d34..e030206 100644 --- a/Server/client.cpp +++ b/Server/client.cpp @@ -34,13 +34,25 @@ static void prepareMelody(PinNumber pin, DynBuffer& buffer){ addTone(duration, 659255, buffer); } static void prepareBlink(PinNumber pin, int count, int high, int low, DynBuffer& buffer){ - printf("pin: %d count: %d high: %d low: %d\n", pin, count, high, low); + printf("blink: pin: %d count: %d high: %d low: %d\n", pin, count, high, low); buffer.clear().append("BLNK"); buffer.appendAsLE((int) pin, 1); buffer.appendAsLE(count, 4); buffer.appendAsLE(high * 1000, 4); buffer.appendAsLE(low * 1000, 4); } +static void prepareTrace(PinNumber pin, int count, int delay){ + printf("trace: pin: %d count: %d delay: %d\n", pin, count, delay); + buffer.clear().append("TRAC"); + buffer.appendAsLE((int) pin, 1); + buffer.appendAsLE(count, 4); + buffer.appendAsLE(delay, 4); +} +static void prepareGetBuffer(const char* bufferName){ + printf("getbuffer: %s\n", buffername); + buffer.clear().append("GETB"); + buffer.append(bufferName); +} void usage(const char* msg, const char* argument){ printf("Usage: client []\n" "\n" @@ -54,10 +66,20 @@ void usage(const char* msg, const char* argument){ " : rpi2_\n" " : 5 7..8 10..16 18..19 21.. 24 26 29 31..33 35..38 40\n" " melody\n" + " trace \n" + " inspects in a fix time raster the input state of a pin times.\n" + " the pause between two checks is microseconds\n" + " returns the name of a buffer which can be requested by 'getbuffer'\n" + " getbuffer \n" + " returns the content of the buffer filled by 'trace'\n" + " if is 't': the server waits for a full buffer\n" + " otherwise the current content of the buffer is returned\n" "Examples:\n" "client -p21222 -h192.168.178.3 blink rpi2_11 99 500\n" "client --port=21222 --host=192.168.178.3 blink rpi2_11 99 500 250\n" "client melody rpi2_12\n" + "client trace rpi2_21 100 1000\n" + "client getbuffer #A t\n" "+++ %s%s%s\n", msg, argument == NULL ? "" : " ", argument == NULL ? "" : argument); exit(1); @@ -91,15 +113,17 @@ int main (int argc, char **argv) { Logger logger; DynBuffer buffer; PinNumber pin; - if (strcmp(argv[1], "blink") == 0){ + int count; + int length = 0; + const char* command = argv[1]; + if (strcmp(command, "blink") == 0){ argv++; argc--; - int length = 0; if (argc < 2) usage("missing pin", NULL); else if ( (pin = pinNameToNumber(argv[1])) == pinUndef) usage("unknown pin:", argv[1]); - int count = 100; + count = 100; if (argc > 2 && (count = toNumber(argv[2], length)) == 0) usage("invalid count", argv[2]); int high = 1000; @@ -109,14 +133,30 @@ int main (int argc, char **argv) { if (argc > 4 && (low = toNumber(argv[4], length)) == 0) usage("invalid high_msec", argv[4]); prepareBlink(pin, count, high, low, buffer); - } else if (strcmp(argv[1], "melody") == 0){ + } else if (strcmp(command, "melody") == 0){ if (argc < 3) usage("missing pin", NULL); else if ( (pin = pinNameToNumber(argv[2])) == pinUndef) usage("unknown pin:", argv[2]); prepareMelody(pin, buffer); + } else if (strcmp(command, "trace") == 0){ + if (argc < 3) + usage("missing pin", NULL); + else if ( (pin = pinNameToNumber(argv[2])) == pinUndef) + usage("unknown pin:", argv[2]); + count = 100; + if (argc > 2 && (count = toNumber(argv[2], length)) == 0) + usage("invalid count", argv[2]); + int delay = 1000; + if (argc > 3 && (count = toNumber(argv[3], length)) == 0) + usage("invalid delay", argv[3]); + prepareTrace(pin, count, delay); + } else if (strcmp(command, "getbuffer") == 0){ + if (argc < 3) + usage("missing buffername", NULL); + prepareGetBuffer(argv[2]); } else { - usage("unknown command:", argv[1]); + usage("unknown command:", command); } TcpClient client(&logger); printf("connection to %s:%d\n", host, port); diff --git a/Server/cpidjinn.cpp b/Server/cpidjinn.cpp index 517c2ba..cfd92be 100644 --- a/Server/cpidjinn.cpp +++ b/Server/cpidjinn.cpp @@ -3,7 +3,8 @@ void blink(PinNumber pin, int count, int duration, Logger* logger){ printf("blink pin: %d count: %d duration: %d\n", pin, count, duration); GPIOProcessor proc(logger); - for (int ix = 0; ix < count; ix++){ + for (int ix = count; ix > 0; ix--){ + printf("%d\n", ix); proc.writeToGPIO(pin, psHigh); usleep(duration * 1000); proc.writeToGPIO(pin, psLow); @@ -17,7 +18,7 @@ void test(int argc, char** argv, Logger* logger){ PinNumber pin = pinRPi2_11; if (argc > 1) - count = pinNameToNumber(argv[1]); + pin = pinNameToNumber(argv[1]); if (argc > 2) count = atol(argv[2]); if (argc > 3) diff --git a/Server/gpioprocessor.cpp b/Server/gpioprocessor.cpp index 75a0780..1e90ea4 100644 --- a/Server/gpioprocessor.cpp +++ b/Server/gpioprocessor.cpp @@ -45,6 +45,26 @@ void GPIOProcessor::blink(DynBuffer& buffer){ } } +/** + * Gets a buffer with data assembled from 'trace'. + * + * Syntax: GETB + * : '#' 'A'..'Z' + * + * @param buffer IN: contains the command describing a melody to play
+ * OUT: answer for the client + */ +void GPIOProcessor::getBuffer(DynBuffer& buffer){ + char name; + if (buffer.length() != 4 + 2 || buffer[4] != '#' || buffer[5] < 'A' || (name = buffer[5]) > 'Z'){ + DynBuffer name(buffer.str() + 4); + buffer.set("ERROR wrong buffername: ").append(name); + } else if(m_buffers[name] == NULL) { + buffer.set("ERROR unknown buffername: #").append(name); + } else { + buffer.set("OK ").append(*m_buffers[name]); + } +} /** * "Writes" a melody to a GPIO pin. * @@ -123,3 +143,18 @@ TcpProcessor::State GPIOProcessor::process(DynBuffer& buffer){ } return rc; } + +/** + * Inspects the input state of a GPIO pin in a timer loop. + * + * Syntax: TRAC[pin][count][delay]
+ * [pin]: 1 byte. Numbering like PinNumber
+ * [count]: 2 byte
+ * [duration]: 4 byte little endian, number of microseconds
+ * + * @param buffer IN: contains the command describing a melody to play
+ * OUT: answer for the client + */ +void TcpProcessor::trace(DynBuffer& buffer){ + +} diff --git a/Server/gpioprocessor.hpp b/Server/gpioprocessor.hpp index f8db49f..9a6bec5 100644 --- a/Server/gpioprocessor.hpp +++ b/Server/gpioprocessor.hpp @@ -15,14 +15,17 @@ private: GPIOProcessor& operator=(const GPIOProcessor& other); private: void blink(DynBuffer& buffer); + void getBuffer(DynBuffer& buffer); void melody(DynBuffer& buffer); void pulseWidthModulation(DynBuffer& buffer); + void trace(DynBuffer& buffer); public: virtual State process(DynBuffer& buffer); private: PinInfo m_pins[MAX_PINS]; Announcer* m_logger; ThreadPool m_pool; + DynBuffer* m_buffers[26]; }; #endif // GPIOPROCESSOR_H diff --git a/Server/gpiotimer.cpp b/Server/gpiotimer.cpp index 9575ae6..ba8a160 100644 --- a/Server/gpiotimer.cpp +++ b/Server/gpiotimer.cpp @@ -29,7 +29,7 @@ GPIOTimer::~GPIOTimer() { * @param state psLow or psHigh */ void GPIOTimer::switchState(PinState state){ - m_logger->sayf(LOG_DEBUG, "pin %d: %c", m_pin, psHigh ? 'H' : 'L'); + m_logger->sayf(LOG_DEBUG, "pin %d: %c", m_pin, state ? 'H' : 'L'); m_processor->writeToGPIO(m_pin, state); } /** @@ -65,3 +65,37 @@ void SquareWaveTimer::timerTask(){ switchState(m_nextHigh ? psHigh : psLow); m_delay = m_nextHigh ? m_high : m_low; } + +/** + * Constructor. + * + * @param pin the target pin + * @param pause the pause (in microseconds) to wait between two reads + * @param count the number of reads + * @param buffer OUT: for each read the state is stored in this buffer + * @param gpioProcessor access to the SoC + * @param logger the logger + * @param pool the pool managing the timer threads + */ +TraceInputTimer::TraceInputTimer(PinNumber pin, uint64_t pause, int count, DynBuffer* buffer, + GPIOProcessor* gpioProcessor, Announcer* logger, ThreadPool* pool) : + GPIOTimer(pin, pause, gpioProcessor, logger, pool), + m_buffer(buffer), + m_lastState(psLow){ + m_taskCount = count; + m_processor->setMode(pin, mInput); +} + +/** + * The action done from the timer. + */ +void TraceInputTimer::timerTask(){ + PinState current = m_processor->readFromGPIO(m_pin); + if (current != m_lastState){ + printf("pin: %d changed to %c\n", m_pin, current == psHigh ? 'H' : 'L'); + m_lastState = current; + } + if (m_buffer != NULL) + m_buffer->append((char) current); +} + diff --git a/Server/gpiotimer.hpp b/Server/gpiotimer.hpp index 58f0d5b..79199f9 100644 --- a/Server/gpiotimer.hpp +++ b/Server/gpiotimer.hpp @@ -36,6 +36,20 @@ private: bool m_nextHigh; }; +/** + * A timer watching states in a given interval. + */ +class TraceInputTimer : public GPIOTimer{ +public: + TraceInputTimer(PinNumber pin, uint64_t pause, int count, DynBuffer* buffer, + GPIOProcessor* gpioProcessor, Announcer* logger, ThreadPool* pool); +public: + virtual void timerTask(); +private: + DynBuffer* m_buffer; + PinState m_lastState; +}; + /** * A timer producing a melody. * -- 2.39.5