Frame Level Language for controlling DUALSHOCK2
fll.cpp
- Committer:
- amutake
- Date:
- 2015-02-19
- Revision:
- 1:905fe1a0ca5a
- Parent:
- 0:a436e2063a3d
File content as of revision 1:905fe1a0ca5a:
// 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(); }