From c5613cf270740e9168cbd27989414a5d496cb67a Mon Sep 17 00:00:00 2001 From: dakkar Date: Sat, 30 Apr 2016 18:16:03 +0100 Subject: maybe this actually loops --- eeg.ino | 178 ++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 107 insertions(+), 71 deletions(-) diff --git a/eeg.ino b/eeg.ino index d55b91f..d8af88b 100644 --- a/eeg.ino +++ b/eeg.ino @@ -8,12 +8,16 @@ template class Queue { E queue[Len]; byte qHead,qTail; public: + Queue() : qHead(0), qTail(0) { } bool empty() { - return qHead == qTail; + return length()==0; } bool full() { - return ((qHead+Len-1)%Len) == qTail; + return length()==Len-1; + } + int length() { + return (qTail+Len-qHead)%Len; } E* current() { return &queue[qHead]; @@ -33,17 +37,23 @@ template class Queue { } }; -#define MK_FREQ 49600L // Set clock to 50kHz (actualy 49.6kHz seems to work better) -#define SOUND (byte)0x52 // Sound controller (device ID 82). Write to 0xA4, read from 0xA5. -#define BUTTON (byte)0x50 // Button controller (device ID 80). Write to 0xA0, read from 0xA1. -#define MOTOR (byte)0x55 // Motor controller (device ID 85). Write to 0xAA, read from 0xAB. - class Keepon { public: - enum State { WAITING=1, READY, QFULL }; - typedef void (*callback)(State); + enum State { WAITING=1, MASTERING, READY, QFULL }; + typedef void (*callback)(State,int); private: static const int maxAttempts = 50; + + // Set clock to 50kHz (actualy 49.6kHz seems to work better) + static const long MK_FREQ = 49600L; + + // Sound controller (device ID 82). Write to 0xA4, read from 0xA5. + static const byte SOUND = 0x52; + // Button controller (device ID 80). Write to 0xA0, read from 0xA1. + static const byte BUTTON = 0x50; + // Motor controller (device ID 85). Write to 0xAA, read from 0xAB. + static const byte MOTOR = 0x55; + struct Command { byte device; byte command; @@ -54,51 +64,65 @@ class Keepon { callback display_callback; - // these two functions need to be loop-friendly! no while, no delay - void take_control() { - digitalWrite(SDA, LOW); - digitalWrite(SCL, LOW); - display_callback(WAITING); - while (analogRead(0) < 512); // Wait until we see voltage on A0 pin - display_callback(READY); - delay(1000); - Wire.begin(); - TWBR = ((F_CPU / MK_FREQ) - 16) / 2; + State current_state; + int last_time; + + void set_state(State value,int n) { + current_state = value; + display_callback(value,n); + } + + void check_state() { + int r = analogRead(0); + int t = millis() - last_time; + if (r <= 512) { + digitalWrite(SDA, LOW); + digitalWrite(SCL, LOW); + set_state(WAITING,r); + } + else if (current_state == WAITING) { + last_time = millis(); + set_state(MASTERING,0); + } + else if (current_state == MASTERING && t > 1000) { + Wire.begin(); + TWBR = ((F_CPU / MK_FREQ) - 16) / 2; + set_state(READY,t/10); + } } - void check_connection() { - if (analogRead(0) > 512) return; - take_control(); - } public: Keepon(callback x) : attempts(0), display_callback(x) { } + void begin() { pinMode(SDA, OUTPUT); // Data wire on My Keepon pinMode(SCL, OUTPUT); // Clock wire on My Keepon - digitalWrite(SDA, LOW); - digitalWrite(SCL, LOW); - } - bool update() { - check_connection(); - if (queue.empty()) return false; - return true; + check_state(); } - void send() { - check_connection(); + + void update() { + check_state(); + + if (current_state != READY) return; + if (attempts > maxAttempts) { attempts = 0; queue.remove(); } + if (queue.empty()) return; Command* current = queue.current(); + Wire.beginTransmission(current->device); Wire.write(current->command); Wire.write(current->arg); int result = (int)Wire.endTransmission(); + if (result == 0) { queue.remove(); + display_callback(current_state,queue.length()); attempts = 0; } else { @@ -108,10 +132,11 @@ class Keepon { void add(const Command&c) { if (queue.full()) { - display_callback(QFULL); + display_callback(QFULL,queue.length()); return; } queue.add(c); + display_callback(current_state,queue.length()); } void pan(byte pos) { @@ -124,16 +149,20 @@ class Keepon { Brain brain(Serial); -void kscan_callback(Keepon::State s) { +void kscan_callback(Keepon::State s, int n) { if (s == Keepon::WAITING) { - uView.setCursor(25,0);uView.println("K?"); + uView.setCursor(25,0);uView.print("K?"); + } + else if (s == Keepon::MASTERING){ + uView.setCursor(25,0);uView.print("K.."); } else if (s == Keepon::READY){ - uView.setCursor(25,0);uView.println("K!"); + uView.setCursor(25,0);uView.print("K!"); } else if (s == Keepon::QFULL){ - uView.setCursor(25,0);uView.println("K+"); + uView.setCursor(25,0);uView.print("KO"); } + uView.setCursor(40,0);uView.print(n); } Keepon keepon(&kscan_callback); @@ -152,46 +181,53 @@ const int hist_width=3; const int hist_pad=1; int samples_delay; +byte attention, meditation, quality; +int hist_height[8]; + void loop() { - byte attention, meditation, quality; - bool bu = brain.update(); bool ku = keepon.update(); - if (bu || ku) { - uView.clear(PAGE); - - if (bu) { - uView.setCursor(0,0); uView.print(quality=brain.readSignalQuality()); - - uView.setCursor(0,9); uView.print(attention=brain.readAttention()); - uView.setCursor(18,9); uView.print(meditation=brain.readMeditation()); - - const uint32_t* power = brain.readPowerArray(); - uint32_t max_value=0; - for (int x=0;x<8;++x) { - if (power[x] > max_value) { - max_value = power[x]; - } + uView.clear(PAGE); + + keepon.update(); + + if (brain.update()) { + quality=brain.readSignalQuality(); + attention=brain.readAttention(); + meditation=brain.readMeditation(); + + const uint32_t* power = brain.readPowerArray(); + uint32_t max_value=0; + for (int x=0;x<8;++x) { + if (power[x] > max_value) { + max_value = power[x]; } + } - for (int x=0;x<8;++x) { - int x0 = (hist_width + hist_pad) * x; - // we have 30 vertical pixels - int height = power[x] * 30 / max_value; - for (int o=0;o 5) { - keepon.pan(attention); - keepon.tilt(meditation); - samples_delay=0; + if (quality < 10 && ++samples_delay > 5) { + keepon.pan(attention); + keepon.tilt(meditation); + samples_delay=0; - uView.setCursor(5,0);uView.print("sent"); - } + uView.setCursor(5,0);uView.print("sent"); } - if (ku) { - keepon.send(); + } + + + uView.setCursor(0,0); uView.print(quality=brain.readSignalQuality()); + + uView.setCursor(0,9); uView.print(attention=brain.readAttention()); + uView.setCursor(18,9); uView.print(meditation=brain.readMeditation()); + + for (int x=0;x<8;++x) { + int x0 = (hist_width + hist_pad) * x; + for (int o=0;o