Frame Level Language for controlling DUALSHOCK2
Diff: fll.cpp
- Revision:
- 0:a436e2063a3d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fll.cpp Thu Feb 19 06:59:49 2015 +0000 @@ -0,0 +1,197 @@ +// Frame Level Language +// implementation + +#include "mbed.h" +#include "rtos.h" +#include "fll.h" + +#include <stdint.h> + +void invoke_sinkrun(const void *p); + +// if you want to debug by `printf`, uncomment next line and put `pc.printf("...", ...);` into certain position. +// Serial pc(USBTX, USBRX); + +// ---- +// Sink +// ---- +Sink::Sink(Producer* src, rtos::Mail<button_t, MAIL_BOX_SIZE>* box, Mutex* mut) +{ + source = src; + mail_box = box; + mutex = mut; + paused = true; + temporary_size = 0; + +} + +void Sink::run() +{ + button_t *btn; + while(1) { + if (paused) { + continue; + } + mutex->lock(); + btn = mail_box->alloc(); + if(!btn) { + mutex->unlock(); + continue; + } + *btn = source->await(); + mail_box->put(btn); + mutex->unlock(); + } +} + +void Sink::resume() +{ + if (!paused) { + return; + } + button_t *btn; + mutex->lock(); + for (int i = 0; i < temporary_size; i++) { + btn = mail_box->alloc(); + *btn = temporary[i]; + mail_box->put(btn); + } + mutex->unlock(); + paused = false; +} + +void Sink::pause() +{ + if (paused) { + return; + } + paused = true; + mutex->lock(); + osEvent e; + int i = 0; + do { + e = mail_box->get(0); + if(e.status == osEventMail) { + mail_box->free((button_t*)e.value.p); + temporary[i++] = *(button_t*)(e.value.p); + } + } while (e.status == osEventMail); + temporary_size = i; + mutex->unlock(); +} + +void Sink::restart() +{ + mutex->lock(); + osEvent e; + do { + e = mail_box->get(0); + if(e.status == osEventMail) { + mail_box->free((button_t*)e.value.p); + } + } while (e.status == osEventMail); + // reset source + source->reset(); + temporary_size = 0; + mutex->unlock(); +} + +void Sink::reset(Producer* src) +{ + mutex->lock(); + // consume current (and actually old) buffer + osEvent e; + do { + e = mail_box->get(0); + if(e.status == osEventMail) { + mail_box->free((button_t*)e.value.p); + } + } while (e.status == osEventMail); + // update source + source = src; + mutex->unlock(); +} + +// ------ +// Output +// ------ +Output::Output(rtos::Mail<button_t, MAIL_BOX_SIZE>* box, FLL *f) +{ + mail_box = box; + fll = f; +} + +void Output::run() +{ + osEvent e = mail_box->get(0); + if (e.status == osEventMail) { // getting is success + button_t b = *(button_t*)(e.value.p); + mail_box->free((button_t*)e.value.p); + fll->press(b); + } else { + fll->press(0); // if mail box is empty + } +} + +FLL::FLL(Producer* p) +{ + producer = p; + + // button_no -> pin (R1 to L1) + PinName ps[] = { + p5, p6, p7, p8, p9, + p10, p11, p12, p13, p14, p15, + p16, p17, p18, p19, + }; + + for(int i = 0; i < BUTTON_NUM; i++) { + off[i] = 1; + pin[i] = new DigitalOut(ps[i], off[i]); + } +} + +FLL::~FLL() +{ + for(int i = 0; i < BUTTON_NUM; i++) { + delete pin[i]; + } +} + +void FLL::press(button_t btn) +{ + for(int i = 0; i < BUTTON_NUM; i++) { + if ((btn >> i) & 0x1) { + pin[i]->write(!off[i]); + } else { + pin[i]->write(off[i]); + } + } +} + +void FLL::run() +{ + + Mail<button_t, MAIL_BOX_SIZE>* mail_box = new Mail<button_t, MAIL_BOX_SIZE>(); + Mutex* mutex = new Mutex(); + Sink* sink = new Sink(producer, mail_box, mutex); + Output* output = new Output(mail_box, this); + + InterruptIn reset_pin(p21); + InterruptIn resume_pin(p22); + InterruptIn pause_pin(p23); + reset_pin.rise(sink, &Sink::restart); + resume_pin.rise(sink, &Sink::resume); + pause_pin.rise(sink, &Sink::pause); + + Thread th(invoke_sinkrun, (void *)sink); + + Ticker ticker; + ticker.attach(output, &Output::run, FRAME); + + Thread::wait(osWaitForever); +} + +static void invoke_sinkrun(const void *p) +{ + ((Sink*)p)->run(); +} \ No newline at end of file