LDFLAGS = -lbcm2835 -lpthread
OBJ_UTIL = timer.o thread.o dynbuffer.o logger.o
-OBJ = gpiotimer.o cpidjinn.o $(OBJ_UTIL) tcpserver.o gpioprocessor.o
+OBJ = systemonachip.o gpiotimer.o cpidjinn.o $(OBJ_UTIL) tcpserver.o gpioprocessor.o
PROG = cpidjinn
OBJ_CLIENT = $(OBJ_UTIL) tcpclient.o client.o
--- /dev/null
+#include "cpidjinn.hpp"
+#include <fcntl.h>
+#include <sys/mman.h>
+
+Bcm2835* Bcm2835::m_instance = NULL;
+
+/**
+ * Constructor.
+ *
+ * @param logger the logger
+ * @param simulation <i>true</i>: the SoC will be simulated.
+ */
+Bcm2835::Bcm2835(Announcer* logger, bool simulation) :
+ m_valid(false),
+ m_simulation(simulation),
+ m_bcmBase(NULL),
+ m_sizeBcmBase(0),
+ m_systemTimerBase(NULL),
+ m_gpioPadsBase(NULL),
+ m_clockBase(NULL),
+ m_gpioBase(NULL),
+ m_spioBase(NULL),
+ m_bscoBase(NULL),
+ m_pwmBase(NULL),
+ m_bsc1Base(NULL),
+ m_simulatorMemory(NULL),
+ m_logger(logger)
+{
+ for (int ix = 0; ix < pinCount; ix++)
+ m_pins[ix].m_pin = (PinNumber) ix;
+
+ /* Figure out the base and size of the peripheral address block
+ // using the device-tree. Required for RPi2, optional for RPi 1
+ */
+ if (m_simulation){
+ int blocksize = 256;
+ m_sizeBcmBase = 8 * blocksize;
+ m_simulatorMemory = new uint32_t[m_sizeBcmBase];
+ m_bcmBase = m_simulatorMemory;
+
+ m_systemTimerBase = m_bcmBase + 0 * blocksize;
+ m_gpioPadsBase = m_systemTimerBase + blocksize;
+ m_clockBase = m_gpioPadsBase + blocksize;
+ m_gpioBase = m_clockBase + blocksize;
+ m_spioBase = m_gpioBase + blocksize;
+ m_bscoBase = m_spioBase + blocksize;
+ m_pwmBase = m_bscoBase + blocksize;
+ m_bsc1Base = m_pwmBase + blocksize;
+ m_valid = true;
+ // for RasPI2 we find the data in the device tree:
+ } else {
+ FILE* fp;
+ const char* fn = "/proc/device-tree/soc/ranges";
+ uint32_t base = 0;
+ if ((fp = fopen(fn, "rb")) == NULL){
+ m_logger->sayf(LOG_ERROR, "not found (%d): %fn", errno, fn);
+ // assuming RasPi1:
+ base = 0x20000000;
+ m_sizeBcmBase = 0x01000000;
+ } else {
+ const int baseOffset = 4;
+ const int sizeOffset = 8;
+
+ ubyte_t buffer[sizeOffset + sizeof (uint32_t)];
+ int readBytes;
+ if ( (readBytes = fread(buffer, 1, sizeof buffer, fp)) != sizeof buffer){
+ m_logger->sayf(LOG_INFO, "cannot read %s (%d): %d instead of %d",
+ errno, fn, readBytes, sizeof buffer);
+ } else {
+ ubyte_t* ptr = buffer + baseOffset;
+ base = ((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]);
+ ptr = buffer + sizeOffset;
+ m_sizeBcmBase = (uint32_t) ((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]);
+ fclose(fp);
+ m_valid = true;
+ }
+ }
+ if (m_valid){
+ fn = "/dev/mem";
+ int handle = open(fn, O_RDWR | O_SYNC);
+ if (handle < 0){
+ m_logger->sayf(LOG_ERROR, "cannot open %s (%d): %d", fn, errno, handle);
+ } else {
+ m_bcmBase = (uint32_t*) mmap(NULL, m_sizeBcmBase, (PROT_READ | PROT_WRITE), MAP_SHARED, handle, base);
+ if (m_bcmBase == MAP_FAILED){
+ m_logger->say(LOG_ERROR, "cannot map GPIO region:");
+ } else {
+ m_systemTimerBase = m_bcmBase + 0x3000 / sizeof (uint32_t);
+ m_gpioPadsBase = m_bcmBase + 0x100000 / sizeof (uint32_t);
+ m_clockBase = m_bcmBase + 0x101000 / sizeof (uint32_t);
+ m_gpioBase = m_bcmBase + 0x200000 / sizeof (uint32_t);
+ m_spioBase = m_bcmBase + 0x204000 / sizeof (uint32_t);
+ m_bscoBase = m_bcmBase + 0x205000 / sizeof (uint32_t);
+ m_pwmBase = m_bcmBase + 0x20C000 / sizeof (uint32_t);
+ m_bsc1Base = m_bcmBase + 0x804000 / sizeof (uint32_t);
+ m_valid = true;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Destructor.
+ */
+Bcm2835::~Bcm2835() {
+}
+
+Bcm2835* Bcm2835::instance(Announcer* logger){
+ if (m_instance == NULL)
+ m_instance = new Bcm2835(logger);
+ return m_instance;
+}
+
+/**
+ * Converts a name of a pin into its number.
+ *
+ * @param name the name of the pin
+ * @return <i>pinUndef</i>: not a name<br>
+ * otherwise: the pin number
+ */
+PinNumber nameToNumber(const char* name){
+ PinNumber rc = pinUndef;
+ if (strnicmp(name, "rpi2_")){
+ int no = atol(name, 5);
+ switch(no){
+ case 3:
+ rc = pinRPi2_03;
+ break;
+ case 5:
+ rc = pinRPi2_05;
+ break;
+ case 7:
+ rc = pinRPi2_07;
+ break;
+ case 8:
+ rc = pinRPi2_08;
+ break;
+ case 10:
+ rc = pinRPi2_10;
+ break;
+ case 11:
+ rc = pinRPi2_11;
+ break;
+ case 12:
+ rc = pinRPi2_12;
+ break;
+ case 13:
+ rc = pinRPi2_13;
+ break;
+ case 15:
+ rc = pinRPi2_15;
+ break;
+ case 16:
+ rc = pinRPi2_16;
+ break;
+ case 18:
+ rc = pinRPi2_18;
+ break;
+ case 19:
+ rc = pinRPi2_19;
+ break;
+ case 21:
+ rc = pinRPi2_21;
+ break;
+ case 22:
+ rc = pinRPi2_22;
+ break;
+ case 23:
+ rc = pinRPi2_23;
+ break;
+ case 24:
+ rc = pinRPi2_24;
+ break;
+ case 26:
+ rc = pinRPi2_26;
+ break;
+ case 29:
+ rc = pinRPi2_29;
+ break;
+ case 31:
+ rc = pinRPi2_31;
+ break;
+ case 32:
+ rc = pinRPi2_32;
+ break;
+ case 33:
+ rc = pinRPi2_33;
+ break;
+ case 35:
+ rc = pinRPi2_35;
+ break;
+ case 36:
+ rc = pinRPi2_36;
+ break;
+ case 37:
+ rc = pinRPi2_37;
+ break;
+ case 38:
+ rc = pinRPi2_38;
+ break;
+ case 40:
+ rc = pinRPi2_40;
+ break;
+ default:
+ break;
+ }
+ }
+ return rc;
+}
+/**
+ * Reads a word from a memory mapped register.
+ *
+ * @param address the address for reading
+ */
+uint32_t Bcm2835::readWord(volatile uint32_t* address){
+ // atomic access:
+ __sync_synchronize();
+ uint32_t rc = *address;
+ __sync_synchronize();
+ return rc;
+}
+
+/**
+ * Sets some bits of a memory mapped register.
+ *
+ * @param address the address of the register
+ * @param value the bits to setBits
+ * @param mask only those bits will be changed which are set in this mask
+ */
+void Bcm2835::setBits(volatile uint32_t* address, uint32_t value, uint32_t mask){
+ uint32_t old = readWord(address);
+ value = (value & mask) | (old & ~mask);
+ writeWord(address, value);
+}
+
+/**
+ * Sets the input/output mode of a pin.
+ *
+ * @param pin the pin which mode has to be changed
+ * @param mode the mode to set
+ */
+void Bcm2835::setMode(PinNumber pin, PinMode mode)
+{
+ ubyte_t mode2 = 255;
+ switch (mode){
+ case mInput:
+ mode2 = 0;
+ break;
+ case mOutput:
+ mode2 = 1;
+ break;
+ default:
+ break;
+ }
+ // mode2 has only 3 bits:
+ if (mode2 >= (1<<3)){
+ m_logger->sayf(LOG_ERROR, "invalid mode: %d", mode);
+ } else {
+ /* Function selects are 10 pins per 32 bit word, 3 bits per pin */
+ const int FUNCTION_SELECT_0 = 0;
+ const int FUNCTION_SELECT_MASK = 0x7;
+ volatile uint32_t* address = m_gpioBase + FUNCTION_SELECT_0/4 + (pin/10);
+ uint8_t shift = (pin % 10) * 3;
+
+ uint32_t mask = FUNCTION_SELECT_MASK << shift;
+ uint32_t bits = mode2 << shift;
+ setBits(address, bits, mask);
+ }
+}
+
+/**
+ * Sets the state of an output pin.
+ *
+ * @param pin the pin number
+ * @param state <i>psHigh</i> or <i>psLow</i>
+ */
+void Bcm2835::setState(PinNumber pin, PinState state){
+ if (pin < 0 || pin >= pinCount){
+ m_logger->sayf(LOG_ERROR, "unknown pin: %d", pin);
+ } else {
+ switch (m_pins[pin].m_mode){
+ case mOutput:
+ break;
+ case mUndef:
+ case mInput:
+ default:
+ setMode(pin, mOutput);
+ break;
+ }
+ writeToGPIO(pin, state);
+ }
+}
+
+/**
+ * Sets the state of a pin in output mode.
+ *
+ * @param pin output pin
+ * @param state the new state
+ */
+void Bcm2835::writeToGPIO(PinNumber pin, PinState state){
+ const int GPinSet0 = 0x001c / sizeof(uint32_t);
+ const int GPinClear0 = 0x0028 / sizeof(uint32_t);
+ volatile uint32_t* addr = m_gpioBase + (state == psHigh ? GPinSet0 : GPinClear0) + pin / 32;
+ uint32_t value = (1 << (pin % 32));
+ writeWord(addr, value);
+
+}
+/**
+ * Writes a 4 byte word to a given address (memory mapped register).
+ *
+ * @param address the target address
+ * @param value value to write
+ */
+void Bcm2835::writeWord(volatile uint32_t* address, uint32_t value){
+ // atomic access:
+ __sync_synchronize();
+ *address = value;
+ __sync_synchronize();
+}
+
--- /dev/null
+#ifndef SYSTEMONACHIP_H
+#define SYSTEMONACHIP_H
+enum PinNumber {
+ pinUndef = -1,
+ // numbering like BCM22835:
+ pinGPIO_00 = 0,
+ pinGPIO_01,
+ pinGPIO_02,
+ pinGPIO_03,
+ pinGPIO_04,
+ pinGPIO_05,
+ pinGPIO_06,
+ pinGPIO_07,
+ pinGPIO_08,
+ pinGPIO_09,
+ pinGPIO_10,
+ pinGPIO_11,
+ pinGPIO_12,
+ pinGPIO_13,
+ pinGPIO_14,
+ pinGPIO_15,
+ pinGPIO_16,
+ pinGPIO_17,
+ pinGPIO_18,
+ pinGPIO_19,
+ pinGPIO_20,
+ pinGPIO_21,
+ pinGPIO_22,
+ pinGPIO_23,
+ pinGPIO_24,
+ pinGPIO_25,
+ pinGPIO_26,
+ pinGPIO_27,
+ pinGPIO_28,
+ pinGPIO_29,
+ pinGPIO_30,
+ pinGPIO_31,
+ pinCount,
+ // RaspberryPi B, B+:
+ pinRPi2_03 = 2,
+ pinRPi2_05 = 3,
+ pinRPi2_07 = 4,
+ pinRPi2_08 = 14,
+ pinRPi2_10 = 15,
+ pinRPi2_11 = 17,
+ pinRPi2_12 = 18,
+ pinRPi2_13 = 27,
+ pinRPi2_15 = 22,
+ pinRPi2_16 = 23,
+ pinRPi2_18 = 24,
+ pinRPi2_19 = 10,
+ pinRPi2_21 = 9,
+ pinRPi2_22 = 25,
+ pinRPi2_23 = 11,
+ pinRPi2_24 = 8,
+ pinRPi2_26 = 7,
+ pinRPi2_29 = 5,
+ pinRPi2_31 = 6,
+ pinRPi2_32 = 12,
+ pinRPi2_33 = 13,
+ pinRPi2_35 = 19,
+ pinRPi2_36 = 16,
+ pinRPi2_37 = 26,
+ pinRPi2_38 = 20,
+ pinRPi2_40 = 21,
+
+ pinWiring_00 = 17,
+ pinWiring_01 = 18,
+ pinWiring_02 = 27,
+ pinWiring_03 = 15,
+ pinWiring_04 = 23,
+ pinWiring_05 = 24,
+ pinWiring_06 = 25,
+ pinWiring_07 = 4,
+ pinWiring_08 = 2,
+ pinWiring_09 = 3,
+ pinWiring_10 = 8,
+ pinWiring_11 = 7,
+ pinWiring_12 = 10,
+ pinWiring_13 = 9,
+ pinWiring_14 = 11,
+ pinWiring_15 = 14,
+ pinWiring_16 = 15,
+};
+enum PinState {
+ psLow,
+ psHigh
+};
+enum PinMode {
+ mUndef,
+ mInput,
+ mOutput
+};
+
+/**
+ * Stores the state and features of a pin.
+ */
+class PinInfo {
+public:
+ /**
+ * Constructor.
+ */
+ PinInfo() :
+ m_pin(pinUndef),
+ m_mode(mUndef),
+ m_timerId(0),
+ m_lastOutputState(psLow)
+ {}
+public:
+ PinNumber m_pin;
+ PinMode m_mode;
+ int m_timerId;
+ PinState m_lastOutputState;
+};
+
+/**
+ * Controlls the access to the periphery of the system on the chip BCM2835.
+ * This is the heart of the raspberry pi.
+ */
+class Bcm2835 {
+protected:
+ Bcm2835(Announcer* logger, bool simulation = false);
+public:
+ ~Bcm2835();
+private:
+ // not implemented. private to avoid usage:
+ Bcm2835 ( const SystemOnAChip& other );
+ SystemOnAChip& operator= ( const SystemOnAChip& other );
+public:
+ SystemOnAChip* instance(Announcer* logger);
+public:
+ uint32_t readWord(volatile uint32_t* addr);
+ void setMode(PinNumber pin, PinMode mode);
+ void setState(PinNumber pin, PinState state);
+ /**
+ * Returns whether the instance is valid.
+ * @return <i>true</code>: the instance is valid (can work)
+ */
+ bool valid() const{
+ return m_valid;
+ }
+ void writeToGPIO(PinNumber pin, PinState state);
+protected:
+ void setBits(volatile uint32_t* addr, uint32_t value, uint32_t mask);
+ void writeWord(volatile uint32_t* addr, uint32_t value);
+private:
+ static PinNumber nameToNumber(const char* name);
+ static SystemOnAChip* m_instance;
+private:
+ bool m_valid;
+ bool m_simulation;
+ uint32_t* m_bcmBase;
+ uint32_t m_sizeBcmBase;
+ volatile uint32_t* m_systemTimerBase;
+ volatile uint32_t* m_gpioPadsBase;
+ volatile uint32_t* m_clockBase;
+ volatile uint32_t* m_gpioBase;
+ volatile uint32_t* m_spioBase;
+ volatile uint32_t* m_bscoBase;
+ volatile uint32_t* m_pwmBase;
+ volatile uint32_t* m_bsc1Base;
+ uint32_t* m_simulatorMemory;
+ Announcer* m_logger;
+ PinInfo m_pins[pinCount];
+};
+
+#endif // SYSTEMONACHIP_H
-#include "util.hpp"
+#include "cpidjinn.hpp"
#include "tcpclient.hpp"
#if 0
buffer.appendAsLE(low, 3);
}
-static void prepareMelody(DynBuffer& buffer){
+static void prepareMelody(const char* name, DynBuffer& buffer){
int duration = 2000;
- int pin = 0;
+ PinNumber pin = Bcm2835::nameToNumber(name);
+ if (pin == pinUndef){
+ printf("unknown pin: %s! Assuming RPi2_11\n", name);
+ ping = pinRPi2_11;
+ }
int countTones = 3;
buffer.clear().append("MELO");
buffer.appendAsLE(pin, 1);
// tone e: 659,255 Hz
addTone(duration, 659255, buffer);
}
+static void prepareblink(const char* name, int count, int high, int low, DynBuffer& buffer){
+ buffer.clear().append("MELO");
+ buffer.appendAsLE(pin, 1);
+}
+void usage(const char* msg, const char* argument){
+ print("Usage: client <opts> <command> [<args>]\n",
+ "<opts>\n"
+ " -p<port> or --port=<port>:\n"
+ " server port. Default: 15000\n"
+ " -h<host> or --host=<host>\n"
+ " server ip. Default: 127.0.0.1\n"
+ "<command>:\n"
+ " blink <count> <pin> <high_millisec> [<low_millisec>]\n"
+ " change <count> times the state of the output pin <pin>
+ " <pin>: rpi2_<number>\n"
+ " <number>: 5 7..8 10..16 18..19 21.. 24 26 29 31..33 35..38 40\n"
+ " melody\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"
+ "+++ %s%s%s\n",
+ msg, argument == NULL ? "" : " ", argument == NULL ? "" : argument);
+ exit(1);
+}
int main (int argc, char **argv) {
const char* host = "127.0.0.1";
+ const char* pin = "RPi2_11";
+ while(argc > 1 && argv[1][0] == '-'){
+ const char* arg = argv[1];
+ if (strncmp(arg, "-p", 2) == 0 || strncmp(arg, "--port=", 7)){
+ port = atol(arg + (arg[1] == '-' ? 2 : 7);
+ if (port <= 0 || port >= 0xffff){
+ usage("illegal port:", arg);
+ }
+ } else if (strncmp(arg, "-h", 2) == 0 || strncmp(arg, "--host=", 7)){
+ host = arg + (arg[1] == '-' ? 2 : 7;
+ if (! isdigit(host[0])){
+ usage("not a numeric ip:", arg);
+ }
+ argc--;
+ argv++;
+ }
int port = 15000;
Logger logger;
DynBuffer buffer;
*/
int main(int argc, char** argv){
Logger logger;
- int port = argc < 2 ? 15000 : atol(argv[1]);
+ bool simulation = false;
logger.say(LOG_INFO, "start");
- GPIOProcessor processor;
+
+ while(argc > 1 && argv[1][0] == '-'){
+ char* arg = argv[1];
+ if (strcmp(arg, "-s") == 0 || strcmp(arg, "--simulation")){
+ simulation = true;
+ } else {
+ logger.sayf(LOG_ERROR, "unknown option: %s", arg);
+ }
+ argc--;
+ argv++;
+ }
+ if (simulation)
+ logger.say(LOG_INFO, "GPIO will be simulated");
+ int port = argc < 2 ? 15000 : atol(argv[1]);
+ GPIOProcessor processor(&logger, simulation);
TcpServer server(port, &logger);
server.addProcessor(processor);
// interpreter for the standard commands:
#ifndef CPIDJINN_HPP
#include "util.hpp"
#include "tcpserver.hpp"
+#include "systemonachip.hpp"
#include "gpioprocessor.hpp"
#include "gpiotimer.hpp"
#endif
#include "cpidjinn.hpp"
-#include "bcm2835.h"
/**
* Constructor.
*/
-GPIOProcessor::GPIOProcessor()
+GPIOProcessor::GPIOProcessor(Announcer* logger, bool simulation) :
+ SystemOnAChip(logger, simulation),
+ TcpProcessor(),
+ m_pins(),
+ m_logger(logger),
+ m_pool(128, logger)
{
}
/**
*/
GPIOProcessor::~GPIOProcessor()
{
-
}
/**
* Lets a GPIO pin blink.
#ifndef GPIOPROCESSOR_H
#define GPIOPROCESSOR_H
-class GPIOProcessor : public TcpProcessor
+#define MAX_PINS 64
+class GPIOProcessor : public SystemOnAChip, public TcpProcessor
{
public:
- GPIOProcessor();
+ GPIOProcessor(Announcer* logger, bool simulation = false);
~GPIOProcessor();
+public:
+ void setState(int pin, bool high);
private:
// not implemented, private use only
GPIOProcessor(const GPIOProcessor& other);
GPIOProcessor& operator=(const GPIOProcessor& other);
+private:
void blink(DynBuffer& buffer);
void melody(DynBuffer& buffer);
void pulseWidthModulation(DynBuffer& buffer);
public:
virtual State process(DynBuffer& buffer);
-
+private:
+ PinInfo m_pins[MAX_PINS];
+ Announcer* m_logger;
+ ThreadPool m_pool;
};
#endif // GPIOPROCESSOR_H
* @param pin the pin where the data will be transferred
* @param pause pause in microseconds befor starting the first hight state
* @param logger the logger
+ * @param pool the pool managing the timer threads
*/
-GPIOTimer::GPIOTimer(int pin, uint64_t pause, Announcer* logger) :
- Timer(1, 0, pause, uMicroSeconds, true, logger),
+GPIOTimer::GPIOTimer(PinNumber pin, uint64_t pause, Announcer* logger, ThreadPool* pool) :
+ Timer(1, 0, pause, uMicroSeconds, true, logger, pool),
m_pin(pin)
{
}
/**
* Switches the state of a pin.
*
- * @param high <i>true</i>: the state will be set to high
+ * @param state <i>psLow</i> or <i>psHigh</i>
*/
-void GPIOTimer::switchState(bool high){
- m_logger->sayf(LOG_DEBUG, "%d: %c", m_pin, high ? 'H' : 'L');
+void GPIOTimer::switchState(PinState state){
+ m_logger->sayf(LOG_DEBUG, "%d: %c", m_pin, psHigh ? 'H' : 'L');
+ m_processor->writeToGPIO(m_pin, state);
}
/**
* Constructor.
* @param count the number of high states to create
* @param high the duration of the high state in microseconds
* @param low the duration of the low state in microseconds
+ * @param logger the logger
+ * @param pool the pool managing the timer threads
*/
-SquareWaveTimer::SquareWaveTimer(int pin, uint64_t pause, int count,
- uint64_t high, uint64_t low, Announcer* logger) :
- GPIOTimer(pin, pause, logger),
+SquareWaveTimer::SquareWaveTimer(PinNumber pin, uint64_t pause, int count,
+ uint64_t high, uint64_t low, Announcer* logger, ThreadPool* pool) :
+ GPIOTimer(pin, pause, logger, pool),
m_pause(pause),
m_high(high),
m_low(low),
*/
void SquareWaveTimer::timerTask(){
m_nextHigh = ! m_nextHigh;
- switchState(m_nextHigh);
+ switchState(m_nextHigh ? psHigh : psLow);
m_delay = m_nextHigh ? m_high : m_low;
}
*/
class GPIOTimer : public Timer {
public:
- GPIOTimer(int pin, uint64_t pause, Announcer* logger);
+ GPIOTimer(PinNumber pin, uint64_t pause, Announcer* logger, ThreadPool* pool);
virtual ~GPIOTimer();
private:
// not implemented, private to avoid usage
GPIOTimer ( const GPIOTimer& other );
GPIOTimer& operator= ( const GPIOTimer& other );
protected:
- void switchState(bool high);
+ void switchState(PinState state);
protected:
- int m_pin;
+ PinNumber m_pin;
+ GPIOProcessor* m_processor;
};
/**
*/
class SquareWaveTimer : public GPIOTimer{
public:
- SquareWaveTimer(int pin, uint64_t pause, int count,
- uint64_t high, uint64_t low, Announcer* logger);
+ SquareWaveTimer(PinNumber pin, uint64_t pause, int count,
+ uint64_t high, uint64_t low, Announcer* logger, ThreadPool* pool);
public:
virtual void timerTask();
private:
*/
class MelodyTimer : public GPIOTimer{
public:
- MelodyTimer(int pin, DynBuffer& melody);
+ MelodyTimer(int pin, DynBuffer& melody, ThreadPool* pool);
public:
virtual void timerTask();
};
#ifndef TCPSERVER_H
#define TCPSERVER_H
-typedef unsigned char ubyte_t;
class TcpProcessor {
public:
#include <sys/time.h>
#include <errno.h>
#include <pthread.h>
+#include <stdint.h>
typedef unsigned char ubyte_t;
-typedef long long unsigned uint64_t;
#include "dynbuffer.hpp"
#include "timeutils.hpp"
#include "logger.hpp"