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

Committer:
petter
Date:
Fri Mar 18 20:58:36 2016 +0000
Revision:
16:7bb8b161e00b
Parent:
15:82c3cc87bd02
Added can.monitor in a trial to get the sleep mode working

Who changed what in which revision?

UserRevisionLine numberNew contents of line
petter 0:6cf6e566c0da 1 // Inspired from BlueSaab
petter 0:6cf6e566c0da 2 // Project/Hardware: http://bluesaab.blogspot.com/
petter 0:6cf6e566c0da 3 // Code: https://github.com/kveilands/SAAB-CDC/tree/master/SAAB-CDC
petter 0:6cf6e566c0da 4 // I-Bus information from http://pikkupossu.1g.fi/tomi/projects/i-bus/i-bus.html
petter 0:6cf6e566c0da 5
petter 11:74844f6ca8cf 6 // Due to power saving functions special firmware required http://mbed.org/users/simon/notebook/interface-powerdown/
petter 11:74844f6ca8cf 7
petter 16:7bb8b161e00b 8 /**** TODO ****
petter 16:7bb8b161e00b 9 Fix sleep mode
petter 16:7bb8b161e00b 10 Implement caller ID retreival
petter 16:7bb8b161e00b 11 Change some public functions to private for both CDC & RN52
petter 16:7bb8b161e00b 12 Instead of sending &res to RN52, add public variables for all data to be communicated
petter 16:7bb8b161e00b 13 rn52.check_event should return event instead of writing to res, (remove if and use switch directly in handle_bt_input
petter 16:7bb8b161e00b 14
petter 16:7bb8b161e00b 15 **** END TODO****/
petter 16:7bb8b161e00b 16
petter 0:6cf6e566c0da 17 #include "mbed.h"
petter 11:74844f6ca8cf 18 #include "PowerControl/PowerControl.h"
petter 11:74844f6ca8cf 19 #include "PowerControl/EthernetPowerControl.h"
petter 11:74844f6ca8cf 20
petter 0:6cf6e566c0da 21 #include "CDC.h"
petter 0:6cf6e566c0da 22 #include "RN52.h"
petter 0:6cf6e566c0da 23
petter 0:6cf6e566c0da 24 CDC cdc;
petter 0:6cf6e566c0da 25 RN52 rn52;
petter 0:6cf6e566c0da 26 RN52_RESULT res;
petter 13:968af0520530 27
petter 11:74844f6ca8cf 28 Ticker wakeup;
petter 0:6cf6e566c0da 29 Serial pc(USBTX, USBRX); // tx, rx
petter 13:968af0520530 30 DigitalOut led3(LED3, 0);
petter 13:968af0520530 31 DigitalOut led4(LED4, 0);
petter 11:74844f6ca8cf 32 bool active = 1;
petter 0:6cf6e566c0da 33
petter 8:beb6c399490a 34 void handle_pc_input();
petter 8:beb6c399490a 35 void handle_cdc_input();
petter 8:beb6c399490a 36 void handle_bt_input();
petter 11:74844f6ca8cf 37 void check_for_wakeup();
petter 8:beb6c399490a 38
petter 8:beb6c399490a 39 int main() {
petter 8:beb6c399490a 40 printf("Petters BT CDC-emulator\r\n");
petter 8:beb6c399490a 41 printf("Initializing\r\n");
petter 11:74844f6ca8cf 42 printf("Disabling unused peripherals to decrease power consumption\r\n");
petter 11:74844f6ca8cf 43 PHY_PowerDown(); // Power down Ethernet interface - saves around 175mW
petter 11:74844f6ca8cf 44 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/
petter 13:968af0520530 45 rn52.init();
petter 8:beb6c399490a 46 cdc.init();
petter 11:74844f6ca8cf 47 printf("Adding wakeup routine\r\n");
petter 14:3f4098e94c29 48 wakeup.attach(&check_for_wakeup, 0.5);
petter 8:beb6c399490a 49 printf("Starting loop\r\n");
petter 8:beb6c399490a 50 while(1) {
petter 11:74844f6ca8cf 51 if(active) {
petter 11:74844f6ca8cf 52 handle_pc_input();
petter 11:74844f6ca8cf 53 handle_cdc_input();
petter 11:74844f6ca8cf 54 handle_bt_input();
petter 11:74844f6ca8cf 55 }
petter 11:74844f6ca8cf 56 else {
petter 11:74844f6ca8cf 57 sleep();
petter 11:74844f6ca8cf 58 }
petter 8:beb6c399490a 59 }
petter 8:beb6c399490a 60 }
petter 8:beb6c399490a 61
petter 11:74844f6ca8cf 62 void check_for_wakeup(){
petter 11:74844f6ca8cf 63 if(!active) {
petter 13:968af0520530 64 led4 = !led4;
petter 11:74844f6ca8cf 65 IBUS_COMMAND cmd = IBUS_OTHER_MESSAGE;
petter 13:968af0520530 66 while(cmd != IBUS_HEAD_UNIT_OFF) {
petter 11:74844f6ca8cf 67 cmd = cdc.get_cmd();
petter 11:74844f6ca8cf 68 if(cmd == IBUS_HEAD_UNIT_ON) {
petter 11:74844f6ca8cf 69 active = 1;
petter 15:82c3cc87bd02 70 cdc.enable();
petter 13:968af0520530 71 rn52.enable();
petter 13:968af0520530 72 }
petter 13:968af0520530 73 }
petter 11:74844f6ca8cf 74 }
petter 11:74844f6ca8cf 75 }
petter 8:beb6c399490a 76
petter 5:8e468fef2754 77 void handle_pc_input() {
petter 5:8e468fef2754 78 //Debug connection to PC
petter 5:8e468fef2754 79 if(pc.readable()) {
petter 5:8e468fef2754 80 switch (pc.getc()) {
petter 5:8e468fef2754 81 case 'p':
petter 5:8e468fef2754 82 if(rn52.toggle_play()) {
petter 5:8e468fef2754 83 printf("play/pause\r\n");
petter 5:8e468fef2754 84 }
petter 5:8e468fef2754 85 break;
petter 5:8e468fef2754 86 case 'v':
petter 5:8e468fef2754 87 printf("volume up\r\n");
petter 5:8e468fef2754 88 rn52.maxvolume();
petter 5:8e468fef2754 89 break;
petter 5:8e468fef2754 90 case 'n':
petter 5:8e468fef2754 91 printf("next track\r\n");
petter 5:8e468fef2754 92 rn52.next_track();
petter 5:8e468fef2754 93 break;
petter 5:8e468fef2754 94 case 'q':
petter 5:8e468fef2754 95 printf("getting status\r\n");
petter 8:beb6c399490a 96 rn52.get_status(&res);
petter 7:2df2c6e8c0df 97 printf("%s\r\n", res.response);
petter 5:8e468fef2754 98 break;
petter 5:8e468fef2754 99 case 't':
petter 8:beb6c399490a 100 rn52.get_caller_id(&res);
petter 7:2df2c6e8c0df 101 printf("%s\r\n", res.response);
petter 5:8e468fef2754 102 break;
petter 15:82c3cc87bd02 103 case 'c':
petter 15:82c3cc87bd02 104 rn52.config("Saab 9-5");
petter 15:82c3cc87bd02 105 printf("configuring RN52\r\n");
petter 15:82c3cc87bd02 106 break;
petter 15:82c3cc87bd02 107 case 'm':
petter 15:82c3cc87bd02 108 rn52.get_track_metadata(&res);
petter 15:82c3cc87bd02 109 printf("Getting metadata\r\n");
petter 15:82c3cc87bd02 110 printf("title: %s\r\n", res.title);
petter 15:82c3cc87bd02 111 printf("artist: %s\r\n", res.artist);
petter 15:82c3cc87bd02 112 printf("album: %s\r\n", res.album);
petter 15:82c3cc87bd02 113 printf("genre: %s\r\n", res.genre);
petter 15:82c3cc87bd02 114 printf("duration: %i\r\n", res.duration);
petter 15:82c3cc87bd02 115 printf("track_count: %i\r\n", res.track_count);
petter 15:82c3cc87bd02 116 printf("track_number: %i\r\n", res.track_number);
petter 15:82c3cc87bd02 117 break;
petter 5:8e468fef2754 118 }
petter 5:8e468fef2754 119 }
petter 5:8e468fef2754 120 }
petter 5:8e468fef2754 121
petter 5:8e468fef2754 122 void handle_cdc_input() {
petter 5:8e468fef2754 123 switch (cdc.get_cmd()) {
petter 11:74844f6ca8cf 124 case IBUS_HEAD_UNIT_OFF:
petter 13:968af0520530 125 active = 0;
petter 14:3f4098e94c29 126 cdc.disable();
petter 13:968af0520530 127 rn52.disable();
petter 5:8e468fef2754 128 break;
petter 5:8e468fef2754 129 case IBUS_NEXT:
petter 15:82c3cc87bd02 130 cdc.display("PLAY_PAUSE");
petter 5:8e468fef2754 131 rn52.toggle_play();
petter 5:8e468fef2754 132 break;
petter 5:8e468fef2754 133 case IBUS_CDC_ON:
petter 15:82c3cc87bd02 134 cdc.display("CDC_ON");
petter 5:8e468fef2754 135 rn52.connect();
petter 5:8e468fef2754 136 break;
petter 5:8e468fef2754 137 case IBUS_CDC_OFF:
petter 15:82c3cc87bd02 138 cdc.display("CDC_OFF");
petter 5:8e468fef2754 139 break;
petter 5:8e468fef2754 140 case IBUS_SKIP_FW:
petter 15:82c3cc87bd02 141 cdc.display("SKIP_FW");
petter 5:8e468fef2754 142 rn52.next_track();
petter 5:8e468fef2754 143 break;
petter 5:8e468fef2754 144 case IBUS_SKIP_BW:
petter 15:82c3cc87bd02 145 cdc.display("SKIP_BW");
petter 5:8e468fef2754 146 rn52.prev_track();
petter 5:8e468fef2754 147 break;
petter 5:8e468fef2754 148 case IBUS_SET:
petter 15:82c3cc87bd02 149 cdc.display("SET");
petter 5:8e468fef2754 150 break;
petter 5:8e468fef2754 151 case IBUS_CLEAR:
petter 15:82c3cc87bd02 152 cdc.display("CLEAR");
petter 5:8e468fef2754 153 break;
petter 5:8e468fef2754 154 }
petter 5:8e468fef2754 155 }
petter 5:8e468fef2754 156
petter 5:8e468fef2754 157 void handle_bt_input() {
petter 5:8e468fef2754 158 if(rn52.check_event(&res)) {
petter 5:8e468fef2754 159 switch (res.event) {
petter 5:8e468fef2754 160 case RN52_CALLER_ID_EVENT:
petter 9:9a4c81493a3d 161 //printf("Caller ID event\r\n");
petter 5:8e468fef2754 162 break;
petter 5:8e468fef2754 163 case RN52_TRACK_CHANGE_EVENT:
petter 5:8e468fef2754 164 cdc.reset_elapsed_time();
petter 14:3f4098e94c29 165 cdc.display(res.title);
petter 8:beb6c399490a 166 cdc.set_track((char)res.track_number);
petter 5:8e468fef2754 167 break;
petter 8:beb6c399490a 168 case RN52_OTHER_EVENT: //no specific event occured, check connection status
petter 5:8e468fef2754 169 switch(res.connection) {
petter 6:c454f88524d6 170 case RN52_CONNECTABLE_DISCOVERABLE:
petter 11:74844f6ca8cf 171 cdc.display("BT REDO");
petter 6:c454f88524d6 172 break;
petter 5:8e468fef2754 173 case RN52_CONNECTED:
petter 11:74844f6ca8cf 174 cdc.display("BT ANSLUTEN");
petter 5:8e468fef2754 175 rn52.maxvolume();
petter 5:8e468fef2754 176 break;
petter 5:8e468fef2754 177 case RN52_AUDIO_STREAMING:
petter 11:74844f6ca8cf 178 cdc.display(res.title);
petter 5:8e468fef2754 179 cdc.start_elapsed_time();
petter 5:8e468fef2754 180 break;
petter 5:8e468fef2754 181 }
petter 5:8e468fef2754 182 if(res.connection != RN52_AUDIO_STREAMING) {
petter 5:8e468fef2754 183 cdc.stop_elapsed_time();
petter 5:8e468fef2754 184 }
petter 5:8e468fef2754 185 }
petter 5:8e468fef2754 186 }
petter 0:6cf6e566c0da 187 }