*.o
+Server/cpidjinn
+Server/client
+*.kdev4
+util/test
+src/
+*.gdb
+cl
+cl.gdb
+sv
+sv.gdb
+sv.sh
+util/test.wav
LDFLAGS = -lbcm2835 -lpthread
OBJ_UTIL = timer.o thread.o dynbuffer.o logger.o
-OBJ = cpidjinn.o $(OBJ_UTIL) tcpserver.o gpioprocessor.o
+OBJ = gpiotimer.o cpidjinn.o $(OBJ_UTIL) tcpserver.o gpioprocessor.o
PROG = cpidjinn
OBJ_CLIENT = $(OBJ_UTIL) tcpclient.o client.o
#include "util.hpp"
#include "tcpserver.hpp"
#include "gpioprocessor.hpp"
+#include "gpiotimer.hpp"
#endif
--- /dev/null
+#include "cpidjinn.hpp"
+
+/**
+ * Constructor.
+ *
+ * @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
+ */
+GPIOTimer::GPIOTimer(int pin, uint64_t pause, Announcer* logger) :
+ Timer(1, 0, pause, uMicroSeconds, true, logger),
+ m_pin(pin)
+{
+}
+
+/**
+ * Destructor.
+ */
+GPIOTimer::~GPIOTimer() {
+
+}
+
+/**
+ * Switches the state of a pin.
+ *
+ * @param high <i>true</i>: the state will be set to high
+ */
+void GPIOTimer::switchState(bool high){
+ m_logger->sayf(LOG_DEBUG, "%d: %c", m_pin, high ? 'H' : 'L');
+}
+/**
+ * Constructor.
+ *
+ * @param pin the target pin
+ * @param pause the pause (in microseconds) to wait before starting the wave
+ * @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
+ */
+SquareWaveTimer::SquareWaveTimer(int pin, uint64_t pause, int count,
+ uint64_t high, uint64_t low, Announcer* logger) :
+ GPIOTimer(pin, pause, logger),
+ m_pause(pause),
+ m_high(high),
+ m_low(low),
+ m_nextHigh(false){
+ // high + low = factor 2:
+ m_count = count * 2;
+}
+
+/**
+ * The action done from the timer.
+ */
+void SquareWaveTimer::timerTask(){
+ m_nextHigh = ! m_nextHigh;
+ switchState(m_nextHigh);
+ m_delay = m_nextHigh ? m_high : m_low;
+}
--- /dev/null
+#ifndef GPIOTIMER_H
+#define GPIOTIMER_H
+
+/**
+ * Abstract base class for controlling "General input output" pins.
+ */
+class GPIOTimer : public Timer {
+public:
+ GPIOTimer(int pin, uint64_t pause, Announcer* logger);
+ virtual ~GPIOTimer();
+private:
+ // not implemented, private to avoid usage
+ GPIOTimer ( const GPIOTimer& other );
+ GPIOTimer& operator= ( const GPIOTimer& other );
+protected:
+ void switchState(bool high);
+protected:
+ int m_pin;
+};
+
+/**
+ * A timer producing a square wave with constant frequency.
+ */
+class SquareWaveTimer : public GPIOTimer{
+public:
+ SquareWaveTimer(int pin, uint64_t pause, int count,
+ uint64_t high, uint64_t low, Announcer* logger);
+public:
+ virtual void timerTask();
+private:
+ int m_count;
+ uint64_t m_pause;
+ uint64_t m_high;
+ uint64_t m_low;
+ bool m_nextHigh;
+};
+
+/**
+ * A timer producing a melody.
+ *
+ * A melody is a squence of square waves with different frequencies.
+ */
+class MelodyTimer : public GPIOTimer{
+public:
+ MelodyTimer(int pin, DynBuffer& melody);
+public:
+ virtual void timerTask();
+};
+
+#endif // GPIOTIMER_H
int ThreadPool::m_currentMaxThreads = 128;
ThreadPool* ThreadPool::m_instance = NULL;
const pthread_mutex_t ThreadPool::m_mutexInitializer = PTHREAD_MUTEX_INITIALIZER;
-
-int gv_rounds = 0;
-int gv_calls;
+pthread_mutex_t Thread::m_mutexStarter = PTHREAD_MUTEX_INITIALIZER;
/**
* Connects the posix thread to the class instance.
*/
void* threadStarter(void *param){
- trace("threadstarter");
+ trace1("threadstarter(%llx)", (uint64_t) param);
Thread* thread = reinterpret_cast<Thread*>(param);
thread->execute();
return param;
m_running = true;
run();
m_pool.remove(*this);
+ pthread_t pthread = m_pthread;
if (m_autoDelete){
trace1("Thread::execute(%d) autodelete\n", m_threadId);
delete this;
}
+ pthread_detach(pthread);
}
/**
* Lets the thread run.
*/
void Thread::start(){
- pthread_create(&m_pthread, NULL, &threadStarter, this);
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
trace2("Thread::start(%d): %lx\n", m_threadId, m_pthread);
+ pthread_create(&m_pthread, &attr, &threadStarter, this);
}
/**
* Introduces the termination of the thread.
trace1("ThreadPool::join(%d):\n", threadId);
void* rc = NULL;
Thread* thread = NULL;
- pthread_t pthread = -1;
- bool running = false;
do {
lock();
thread = findById(threadId);
- if(thread == NULL){
- unlock();
- break;
- } else {
- pthread = thread->m_pthread;
- running = thread->m_running;
- }
unlock();
- if (! running)
+ if (thread != NULL)
Thread::microSleep(10*1000);
- } while(! running);
- trace2("join: thread: %c %lx\n", thread != NULL ? 't' : 'f', pthread);
- // Does the thread already exist?
- if (pthread != (pthread_t) -1)
- pthread_join(pthread, &rc);
- trace1("join: rc: %c\n", rc == NULL ? 't' : 'f');
+ } while(thread != NULL);
+ trace2("join: thread: %c %llx\n", thread != NULL ? 't' : 'f', (uint64_t) thread);
return rc;
}
private:
friend void* threadStarter(void *);
void execute();
+private:
+ static pthread_mutex_t m_mutexStarter;
protected:
int m_threadId;
bool m_shouldStop;
Timer::Timer(int count, int delay, int m_startDelay, Unit unit,
bool autoDelete, Announcer* logger, ThreadPool* pool) :
Thread(logger, autoDelete, pool),
- m_count(count),
+ m_taskCount(count),
m_delay(delay),
m_startDelay(delay),
m_unit(unit)
*/
void Timer::run(){
trace1("Timer::run(%d)\n", threadId());
- if (m_startDelay > 0){
- switch (m_unit){
- case uSeconds:
- sleep(m_startDelay);
- break;
- case uMilliSeconds:
- microSleep(m_startDelay * 1000);
- break;
- case uMicroSeconds:
- default:
- microSleep(m_startDelay);
- break;
- }
+ if (! m_shouldStop && m_startDelay > 0){
+ sleep(m_startDelay);
}
- while(m_count-- > 0){
+ while(! m_shouldStop && m_taskCount-- > 0){
trace2("Timer::run(%d): %d\n", threadId(), m_count);
timerTask();
- switch (m_unit){
- case Timer::uSeconds:
- sleep(m_delay);
- break;
- case Timer::uMilliSeconds:
- microSleep(m_delay * 1000);
- break;
- case Timer::uMicroSeconds:
- usleep(m_delay);
- break;
- default:
- break;
- }
+ sleep(m_delay);
}
}
+
+/**
+ * Sleeps a given amount of microseconds.
+ *
+ * The sleep is broken if a stop request is done.
+ *
+ * @param units time to wait in units given by <i>m_unit</i>
+ */
+void Timer::sleep(int units){
+ uint64_t microseconds;
+ switch (m_unit){
+ case uSeconds:
+ microseconds = units * (uint64_t) 1000000;
+ break;
+ case uMilliSeconds:
+ microseconds = units * (uint64_t) 1000;
+ break;
+ case uMicroSeconds:
+ default:
+ microseconds = units;
+ break;
+ }
+ while(! m_shouldStop && microseconds >= (uint64_t) 2000000){
+ sleep(1);
+ microseconds -= 1000000;
+ }
+ if (! m_shouldStop)
+ Thread::microSleep(microseconds);
+}
virtual void timerTask() = 0;
private:
virtual void run();
-private:
- int m_count;
+ void sleep(int units);
+protected:
+ int m_taskCount;
int m_delay;
int m_startDelay;
Unit m_unit;