Simulated the CD changer of a Saab to implement a bluetooth connection to the car stereo. Control of playback device (phone) with steering wheel buttons. Needs a RN52 bluetooth transciever and a CAN transiever. So far only audio playback and control via steering wheel buttons implemented. Hands free calling planned.

Dependencies:   mbed

main.cpp

Committer:
petter
Date:
2016-03-18
Revision:
16:7bb8b161e00b
Parent:
15:82c3cc87bd02

File content as of revision 16:7bb8b161e00b:

// Inspired from BlueSaab
// Project/Hardware: http://bluesaab.blogspot.com/
// Code: https://github.com/kveilands/SAAB-CDC/tree/master/SAAB-CDC
// I-Bus information from http://pikkupossu.1g.fi/tomi/projects/i-bus/i-bus.html

// Due to power saving functions special firmware required http://mbed.org/users/simon/notebook/interface-powerdown/

/**** TODO ****
Fix sleep mode
Implement caller ID retreival
Change some public functions to private for both CDC & RN52
Instead of sending &res to RN52, add public variables for all data to be communicated
rn52.check_event should return event instead of writing to res, (remove if and use switch directly in handle_bt_input

**** END TODO****/

#include "mbed.h"
#include "PowerControl/PowerControl.h"
#include "PowerControl/EthernetPowerControl.h"

#include "CDC.h"
#include "RN52.h"

CDC cdc;
RN52 rn52;
RN52_RESULT res;

Ticker wakeup;
Serial pc(USBTX, USBRX); // tx, rx
DigitalOut led3(LED3, 0);
DigitalOut led4(LED4, 0);
bool active = 1;

void handle_pc_input();
void handle_cdc_input();
void handle_bt_input();
void check_for_wakeup();

int main() {
    printf("Petters BT CDC-emulator\r\n");
    printf("Initializing\r\n");
    printf("Disabling unused peripherals to decrease power consumption\r\n");
    PHY_PowerDown(); // Power down Ethernet interface - saves around 175mW
    semihost_powerdown(); // If you don't need the PC host USB interface power down magic USB interface chip - saves around 150mW | Needs new firmware (URL below) and USB cable not connected http://mbed.org/users/simon/notebook/interface-powerdown/
    rn52.init();
    cdc.init();
    printf("Adding wakeup routine\r\n");
    wakeup.attach(&check_for_wakeup, 0.5);
    printf("Starting loop\r\n");
    while(1) {
        if(active) {
            handle_pc_input();
            handle_cdc_input();
            handle_bt_input();
        }
        else {
            sleep();
        }
    }
}

void check_for_wakeup(){
    if(!active) {
        led4 = !led4;
        IBUS_COMMAND cmd = IBUS_OTHER_MESSAGE;
        while(cmd != IBUS_HEAD_UNIT_OFF) {
            cmd = cdc.get_cmd();
            if(cmd == IBUS_HEAD_UNIT_ON) {
                active = 1;
                cdc.enable();
                rn52.enable();
            }
        }
    }
}

void handle_pc_input() {
    //Debug connection to PC
    if(pc.readable()) {
        switch (pc.getc()) {
            case 'p':
                if(rn52.toggle_play()) {
                    printf("play/pause\r\n");
                }
                break;
            case 'v':
                printf("volume up\r\n");
                rn52.maxvolume();
                break;             
            case 'n':
                printf("next track\r\n");
                rn52.next_track();
                break;  
            case 'q':
                printf("getting status\r\n");
                rn52.get_status(&res);
                printf("%s\r\n", res.response);
                break;
            case 't':
                rn52.get_caller_id(&res);
                printf("%s\r\n", res.response);
                break;
            case 'c':
                rn52.config("Saab 9-5");
                printf("configuring RN52\r\n");
                break;
            case 'm':
                rn52.get_track_metadata(&res);
                printf("Getting metadata\r\n");
                printf("title:  %s\r\n", res.title);
                printf("artist: %s\r\n", res.artist);
                printf("album:  %s\r\n", res.album);
                printf("genre:  %s\r\n", res.genre);
                printf("duration:  %i\r\n", res.duration);
                printf("track_count:  %i\r\n", res.track_count);
                printf("track_number:  %i\r\n", res.track_number);                
                break;
        }
    }
}

void handle_cdc_input() {
    switch (cdc.get_cmd()) {
        case IBUS_HEAD_UNIT_OFF:
            active = 0;
            cdc.disable();
            rn52.disable();
            break;
        case IBUS_NEXT:
            cdc.display("PLAY_PAUSE");
            rn52.toggle_play();
            break;
        case IBUS_CDC_ON:
            cdc.display("CDC_ON");
            rn52.connect();
            break;
        case IBUS_CDC_OFF:
            cdc.display("CDC_OFF");
            break;
        case IBUS_SKIP_FW:
            cdc.display("SKIP_FW");
            rn52.next_track();
            break;
        case IBUS_SKIP_BW:
            cdc.display("SKIP_BW");
            rn52.prev_track();
            break;
        case IBUS_SET:
            cdc.display("SET");
            break;
        case IBUS_CLEAR:
            cdc.display("CLEAR");
            break;
    }    
}

void handle_bt_input() { 
    if(rn52.check_event(&res)) {
        switch (res.event) {
            case RN52_CALLER_ID_EVENT:
                //printf("Caller ID event\r\n");
                break;
            case RN52_TRACK_CHANGE_EVENT:
                cdc.reset_elapsed_time();
                cdc.display(res.title);
                cdc.set_track((char)res.track_number);
                break;
            case RN52_OTHER_EVENT: //no specific event occured, check connection status
                switch(res.connection) {
                    case RN52_CONNECTABLE_DISCOVERABLE:
                        cdc.display("BT REDO");
                        break;
                    case RN52_CONNECTED:
                        cdc.display("BT ANSLUTEN");
                        rn52.maxvolume();
                        break;
                    case RN52_AUDIO_STREAMING:
                        cdc.display(res.title);
                        cdc.start_elapsed_time();
                        break;
                }         
                if(res.connection != RN52_AUDIO_STREAMING) {
                    cdc.stop_elapsed_time();
                }            
        }
    }
}