run this here

Dependencies:   Hexi_KW40Z Hexi_OLED_SSD1351

main.cpp

Committer:
trhackett
Date:
2018-04-27
Revision:
2:75253a344332
Parent:
1:b965810f9bb3
Child:
3:f34bbdea0786

File content as of revision 2:75253a344332:

#include "mbed.h"
#include "Ticker.h"
#include <stdlib.h>

InterruptIn catchChange(PTD2);
Serial pc(USBTX, USBRX);

// software PWM using DigitalOut
DigitalOut pulse(PTA10);

float PERIOD = 0.06f;
float DUTYCYCLE = 0.50f;

// period and duty cycle that we'll be changing
float currentPeriod = PERIOD;
float currentDutyCycle = DUTYCYCLE;

// period is the time between the previous rising edge
// and the current one, so recompute each time you
// encounter a rising edge
float period;
Timer t;

// D is fraction of time that was high during the preceding interval
float D;
Timer highTime;
Timer lowTime;

// every 10 rising edges, print T and D
int risingEdges = 0;

// add in a thread that will do printing so it 
// doesn't interfere with my measurements
EventQueue q1;
Thread t1;

// ticker to change from low to high and one to change from high to low
Ticker lowToHigh; // low to high every period seconds
Ticker highToLow; // high to low every period + period * duty_cycle seconds

// switch the digital signal whenever the ticker goes off
void tickerHandle() {
    if (pulse.read() == 1) {
        pulse.write(0);   
    } else {
        pulse.write(1);
    }
}

void printData() {
    // this does not run in the ISR
    pc.printf("mbed> %i, %.3f\n\r",(int)(period*1000000.0f),D);
}

void riseHandle() {
    // recompute the period
    period = t.read();
    t.reset();
    t.start();
    
    // if it's the first rising edge of a 10 edge interval,
    // then reset both timers
    if (risingEdges == 0) {
        lowTime.reset();
        highTime.reset();
        lowTime.stop();
        highTime.start();
        
        // and you're in high time on the first rising edge
        risingEdges++;
    }
    
    // if it's the tenth, then store D so that someone else can
    // print it out. reset the timers and rising edge count
    else if (risingEdges >= 9) {
        float h = highTime.read();
        float l = lowTime.read();
        D = h / (h + l);
        
        lowTime.reset();
        highTime.reset();
        lowTime.stop();
        highTime.start();
        
        risingEdges++;
    }
    
    // if it's rising edge 2 ... 9, then just increment and start
    // the high timer and stop the low timer
    else {
        risingEdges++;
        lowTime.stop();
        highTime.start(); 
    }
    
    // then defer the possible printf call to the other thread
    if (risingEdges == 10) {
        q1.call(&printData);
        risingEdges = 0;
    }
}

// when you come to a falling edge, you should stop the high timer and
// start the low timer
void fallHandle() {
    lowTime.start();
    highTime.stop();   
}

void inputHandle() {
    char buff[256];
    gets(buff);
    
    // extract out the values from the character array
    int i = 0;
    char p[20];
    while (buff[i] != ',') {
        p[i] = buff[i];
        ++i;
    }
    p[i] = '\0';
    
    i += 2;
    int j = 0;
    char dc[20];
    while (buff[i] != '\0') {
        dc[j] = buff[i];
        ++i;
        ++j;
    }
    
    int T_temp = atoi(p);
    float D_temp = atof(dc);
   
    // make the changes to the period and duty cycle as long
    // as they are within range
    if ((T_temp >= 1000.0f && T_temp <= 60000.0f) &&
        (D_temp >= 0.0f && D_temp <= 1.0f))
    {
        currentPeriod = ((float)T_temp) / 1000000.0f;
        currentDutyCycle = D_temp;
        
        // set to low
        pulse.write(0);
        
        // reset the low to high ticker
        lowToHigh.detach();
        lowToHigh.attach(&tickerHandle, currentPeriod);
        
        highToLow.detach();
        
        // wait period * duty cycle
        wait(currentPeriod * currentDutyCycle);
        // reset the high to low ticker
        highToLow.attach(&tickerHandle, currentPeriod);
    }
    
    // print an error, non-blocking, if they input bad values
    else {
        q1.call(printf,"mbed> ERROR\r\n");   
    }
}

// main() runs in its own thread in the OS
int main() {
    
    // each time you see a rising edge, recompute the period
    // and stop timing the low signal
    catchChange.rise(&riseHandle);
    catchChange.fall(&fallHandle);
    
    // when the user inputs something
    pc.attach(&inputHandle);
    
    // start low
    pulse.write(0);
    
    // 1) ticker that goes from low to high every period seconds
    lowToHigh.attach(&tickerHandle, currentPeriod);
    // 2) wait period * duty cycle
    wait(currentPeriod * currentDutyCycle);
    // 3) ticker that goes from high to low every period seconds
    highToLow.attach(&tickerHandle, currentPeriod);
    
    t1.start(callback(&q1, &EventQueue::dispatch_forever));
    
    wait(osWaitForever);
}