Code written by Paul Rabbat, Angel Daruna, Jarel Hawkins, and Cordel Williams

Dependencies:   4DGL-uLCD-SE EthernetInterface HTTPClient NTPClient PinDetect SDFileSystem mbed-rpc mbed-rtos mbed wave_player

Fork of ECE4180_FinalProject by Angel Daruna

main.cpp

Committer:
prabbat3
Date:
2014-12-07
Revision:
12:a99989062fee
Parent:
10:89cd9b6a251e

File content as of revision 12:a99989062fee:

// Includes
#include "SDFileSystem.h"
#include "PinDetect.h"
#include "mbed.h"
#include "NTPClient.h"
#include "uLCD_4DGL.h"
#include "EthernetInterface.h"
#include <vector>
#include <string>
#include "mbed_rpc.h"
#include "RPCCommand.h"
#include "HTTPServer.h"
#include "Formatter.h"
#include "RequestHandler.h"
#include "RPCType.h"
#include "alarmContainer.h"
#include "wave_player.h"
#include "HTTPClient.h"

// Defines
#define SERVER_PORT 80 //HTTPSERVER

// Global variables
EthernetInterface eth;
uLCD_4DGL uLCD(p28, p27, p29); // serial tx, serial rx, reset pin;
alarmModel _alarm;
string dayOfWeek, month, dayNum, ampm;
int hour, minute, sec;
PwmOut led1(LED1); // led 1 indicates dim value
DigitalOut led2(LED2); // led 2 indicates delay time for interrupts
DigitalOut led3(LED3); // Indicates the alarm has been set 
DigitalOut led4(LED4);  // Indiciates the alarm is going off
int alarmSignaled = 0;
PwmOut alarm(p25);
AnalogOut DACout(p18);
PinDetect snooze(p23);
PinDetect stop(p24);
SDFileSystem sd(p5, p6, p7, p8, p12, "sd"); //SD card
FILE *wave_file;
string filepath = "/sd/mymusic/";
string weatherCondition = "";
string lowTemperature = "";
string highTemperature = "";
volatile bool t = true;
volatile bool play = true;
volatile float vol = .52;
volatile bool insert;
volatile int index;
wave_player waver(&DACout);
int num = 0;
vector<string> filenames; //filenames are stored in a vector string

// pin for ZeroCross tail input
// An external 1K pullup required
InterruptIn zerocross(p22);
 
// pin for PowerSSRtail output
DigitalOut SSR(p21);
 
//use timer interrupts to control dimming
Timeout SSRtriggerOn;
 
// dimmer value 0.0=off and 1.0=full on
volatile float dim;
 
// AC power line frequency
const float powerlinefrequency=60.000;

// Function prototypes
HTTPServer create_simple_server();
HTTPServer create_interactive_server();
void stop_hit_callback(void);
void snooze_hit_callback(void);
void read_file_names(char *dir);
void play_wake_up(void);
void thread_server(void const *args);
void thread_display(void const *args);
void thread_alarm(void const *args);
void triggerOn();
void dimmer();
void turn_on();
void getAndParseWeather();
char* getWeather();
void getTime();
void parseResults(char*);

int main() {
    snooze.mode(PullUp);
    stop.mode(PullUp);
    wait(.01);
    snooze.attach_deasserted(&snooze_hit_callback);
    stop.attach_deasserted(&stop_hit_callback);
    stop.setSampleFrequency(); 
    snooze.setSampleFrequency(); //default is 20KHz sampling
    
    insert = sd.SD_inserted();
    if(insert){
        printf("Inserted worked.");
    }
    printf("Attempting to read file names");
    read_file_names("/sd/myMusic");
    printf("File names read");
    
    wave_file = fopen( (filepath+filenames[index]).c_str(), "r");
    printf("Wave file opened");
    
    dim = -1.0;
    printf("Getting IP Address.. ");
    uLCD.baudrate(2000000);
    uLCD.cls();
    uLCD.background_color(BLACK); 
    uLCD.textbackground_color(BLACK);
    uLCD.locate(0,0);
    uLCD.color(BLUE);
    uLCD.text_height(2);
    uLCD.text_width(2);
    uLCD.printf("\n\nUniv Time\n  Clock\n");
    uLCD.text_height(1);
    uLCD.text_width(1);
    uLCD.printf("    Loading...\n");
    uLCD.locate(0,0);
    
    if(eth.init())
    {
        printf("Error while initializing the ethernet interface.\n");
        return -1;
    }
    wait(5);
    if(eth.connect())
    {
        printf("Error while starting the ethernet interface.\n");
        return -1;
    }
    
    printf("IP Address is %s\n", eth.getIPAddress());
    
    getAndParseWeather();
    wait(1);
    getTime();
    wait(1);
    
    //set up interrupt routine to detect AC line zero crossings
    zerocross.mode(PullNone);
    wait(.2);
    zerocross.rise(&dimmer);
    // main program only sets dimmer level (dim)
    // interrupt routines dim the light

    Thread t1(thread_server); //start thread_server
    Thread t2(thread_display);
    Thread t3(thread_alarm);
    
    while(1){
        led1=!led1;
        Thread::wait(1000);
    }
}

void getAndParseWeather(){
    char* buf = getWeather();
    wait(1);
    parseResults(buf);    
}

char* getWeather(){
    /*** WEATHER****/
    char buf[3000];
    printf("Getting weather..\n");
    HTTPClient http; 
    int retHttp = http.get("http://weather.yahooapis.com/forecastrss?w=2357024&u=f", buf, sizeof(buf));
    
    switch(retHttp){
    case HTTP_OK:
        printf("Read completely\n");    
        break;
    case HTTP_TIMEOUT:
        printf("Connection Timeout\n");          
        break;
    case HTTP_CONN:
        printf("Connection Error\n");
        break;
    default:
        printf("Error\n");                        
    }
    
    return buf;        
}

void parseResults(char* buf){
    printf("Starting parser\n");  
    int i=0;
    char* chars_array = strtok(buf, "\"");
    while(chars_array)
    {
        if(i==63){
            lowTemperature = chars_array;
            printf("Low temp: %s F\n", lowTemperature);
        }
        else if(i==65){
            highTemperature = chars_array;
            printf("Low temp: %s F\n", highTemperature);
        }
        else if (i==67){
            weatherCondition = chars_array;
            printf("Weather: %s\n", weatherCondition);
        }
        
        i++;
        chars_array = strtok(NULL, "\"");
    }
    
    printf("Parser complete!\n");
}

void getTime(){
    NTPClient ntpClient;
    printf("Reading time..\n");
    char* domainName="us.pool.ntp.org"; //SET TO DOMAIN NAME OF SERVER GETTING TIME FROM
    //GETS THE TIME FROM THE SERVER
    //setTime(DOMAIN_NAME,PORT_NUMBER,TIME_OUT)
    //DOMAIN_NAME= domain name
    //PORT NUMBER=port number (123 for NTP)
    //TIME_OUT= timeout value for request
    ntpClient.setTime(domainName,123,0x00005000);
    printf("Time set.\n");    
}

void thread_alarm(void const *args)
{
    while(1){
        if(_alarm.alarmSet && !alarmSignaled){
            led3 = 1;
            if(_alarm.hours == hour && _alarm.minutes == minute && _alarm.amPm == ampm){
                alarmSignaled = 1;
                //increase brightness
                for(dim = 0.0; dim <= 1.0; dim += 0.025) {
                    led1 = (dim < 0 ? 0 : dim);
                    wait(0.3);
                }
                dim = 1.0;
                led4 = 1;
                play_wake_up();
            }
        }
        Thread::wait(100);
    }       
}

void thread_display(void const *args){
    time_t ctTime; //system time structure
    uLCD.cls();
    uLCD.locate(0,0);
    uLCD.text_height(2);
    uLCD.text_width(1);
    char buffer[80]; //BUFFER TO HOLD FORMATTED TIME DATA
    uLCD.textbackground_color(BLACK);
    
    while (1) {
       
        uLCD.locate(0,0);
        uLCD.color(RED);
        // loop and periodically update the LCD's time display
        ctTime = time(NULL)-(3600*4);  //TIME with offset for eastern time US
        
        //FORMAT TIME FOR DISPLAY AND STORE FORMATTED RESULT IN BUFFER
        strftime(buffer,80,"%a %b %d %T %p %z %Z",localtime(&ctTime));
        
        int i=0;
        char* chars_array = strtok(buffer, " :");
        while(chars_array)
        {
            switch(i){
                case 0:
                    dayOfWeek = chars_array;
                    break;
                case 1:
                    month = chars_array;
                    break;
                case 2:
                    dayNum = chars_array;
                    break;    
                case 3:
                    int hourTemp = atoi(chars_array); 
                    hourTemp--; //Daylight savings
                    if(hourTemp > 12) hourTemp -= 12;
                    hour = hourTemp;
                    break; 
                case 4:
                    minute = atoi(chars_array);
                    break; 
                case 5:
                    sec = atoi(chars_array);
                    break; 
                case 6:
                    ampm = chars_array;
                    break;
            }
            i++;
            chars_array = strtok(NULL, " :");
        }
        
        uLCD.printf("    %s, %s %s\n    %02d:%02d:%02d %s\n", dayOfWeek, month, dayNum, hour, minute, sec, ampm);
        uLCD.color(BLUE);
        uLCD.printf("    Low: %s F\n    High: %s F\n    Weather:\n  %s", lowTemperature, highTemperature, weatherCondition);
        if(_alarm.alarmSet){
            uLCD.locate(0,6);
            uLCD.color(GREEN);
            uLCD.printf("    Alarm:\n    %d:%02d %s", _alarm.hours, _alarm.minutes, _alarm.amPm);
        }
        
        Thread::wait(100);
    }  
}

void thread_server(void const *args)
{
    RPCType::instance().register_types();
    HTTPServer srv = create_interactive_server();

    if(!srv.init(SERVER_PORT))
    {
        eth.disconnect();
        printf("Thread 1 error.\n");
        return;
    }

    srv.run();
}

HTTPServer create_simple_server()
{    
    HTTPServer srv;
    srv.add_request_handler("DELETE", new DeleteRequestHandler());
    srv.add_request_handler("GET", new GetRequestHandler());
    srv.add_request_handler("PUT", new PutRequestHandler());
    return srv;
}

HTTPServer create_interactive_server()
{
    HTTPServer srv(new InteractiveHTMLFormatter());
    srv.add_request_handler("GET", new ComplexRequestHandler());
    return srv;
}  

// this interrupt routine is activated after a time delay set by dim value
void triggerOn()
{
    SSR = 1;
    led2=0;
}

// this interrupt routine is activated by every AC line zero crossing
// it is needed to synchronize the SSR turnon time delay to the AC line
void dimmer()
{
    // turn off SSR at zero crossing
    SSR = 0;
    // compute time delay using dim value and set timer interrupt
    // triggers SSR after a small post zero crossing time delay
    SSRtriggerOn.attach(&triggerOn,(1.001-dim)/(2*powerlinefrequency));
    led2=1;
}

void turn_on(){
    //increase brightness
    for(dim = 0.0; dim <= 1.0; dim += 0.005) {
        led1 = (dim < 0 ? 0 : dim);
        wait(0.3);
    }
    dim = 1.0;
}

void stop_hit_callback(void){
   vol = 0.0;
   t = false;
   if (insert == true){
       play = !play;
    }
}

void snooze_hit_callback(void) {
    alarm = 0.0;
    wait(5);
    if (insert == true) {
        play =! play;
        wait(5);
        play =! play;
    }
}

void read_file_names(char *dir)
{
    DIR *dp;
    struct dirent *dirp;
    dp = opendir(dir);
    //read all directory and file names in current directory into filename vector
    while((dirp = readdir(dp)) != NULL) {
        filenames.push_back(string(dirp->d_name));
        num++;
    }
    num= num;
}

void play_wake_up(void){
    while(t == true) {
        printf("Started playing.");
        if ((insert == true) && (play ==true)) {
                waver.play(wave_file, &play);
               if (feof(wave_file)) // when playback ends file will close and play will equal false
                {
                fclose(wave_file);
                printf("Wav ended.");
                } 
                 
            }
        if ((insert == false)&&(play == true)) {
            // generate a 500Hz tone using PWM hardware output
            for (int j=0; j<26; j=j+2) {
                alarm.period(1.0/500.0); // 500hz period
                alarm =vol; //50% duty cycle - max volume
                wait(.5);
                alarm.period(0.0/500.0);
                wait(.5);
                } // end of for
        
            // two tone police siren effect -  two periods or two frequencies
            // increase volume - by changing the PWM duty cycle
            for (int i=0; i<26; i=i+2) {
                alarm = vol;
                alarm.period(1.0/969.0);
                wait(.5);
                alarm.period(1.0/800.0);
                wait(.5);
            } 
        } 
    }
    alarm = 0.0;
}