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.
RN52.cpp@0:6cf6e566c0da, 2016-01-04 (annotated)
- Committer:
- petter
- Date:
- Mon Jan 04 15:31:12 2016 +0000
- Revision:
- 0:6cf6e566c0da
- Child:
- 1:63db3f3124d4
First commit.; Fully working cdc emulator. Control Playback with steering wheel buttons.; Debug outputs on SID.; Playback information to NAV unit not perfect.; RN52 not upgraded to 1.16 so no handling of track metadata.; No handling of phone profile.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
petter | 0:6cf6e566c0da | 1 | #include "RN52.h" |
petter | 0:6cf6e566c0da | 2 | #include "mbed.h" |
petter | 0:6cf6e566c0da | 3 | |
petter | 0:6cf6e566c0da | 4 | // RN52 action command definitions |
petter | 0:6cf6e566c0da | 5 | #define PLAYPAUSE "AP\r" |
petter | 0:6cf6e566c0da | 6 | #define NEXTTRACK "AT+\r" |
petter | 0:6cf6e566c0da | 7 | #define PREVTRACK "AT-\r" |
petter | 0:6cf6e566c0da | 8 | #define CONNECT "B\r" |
petter | 0:6cf6e566c0da | 9 | #define DISCONNECT "@,1\r" |
petter | 0:6cf6e566c0da | 10 | #define REBOOT "R,1\r" |
petter | 0:6cf6e566c0da | 11 | #define VOLUMEUP "AV+\r" |
petter | 0:6cf6e566c0da | 12 | #define MAXVOLUME "SS,0F\r" |
petter | 0:6cf6e566c0da | 13 | #define GETSTATUS "Q\r" |
petter | 0:6cf6e566c0da | 14 | #define ASSISTANT "P\r" |
petter | 0:6cf6e566c0da | 15 | #define CALLER_ID "T\r" |
petter | 0:6cf6e566c0da | 16 | #define TRACK_METADATA "AD\r" |
petter | 0:6cf6e566c0da | 17 | |
petter | 0:6cf6e566c0da | 18 | |
petter | 0:6cf6e566c0da | 19 | Serial serial(p13, p14); // tx, rx |
petter | 0:6cf6e566c0da | 20 | DigitalIn event_pin(p20); |
petter | 0:6cf6e566c0da | 21 | |
petter | 0:6cf6e566c0da | 22 | void RN52::init(){ |
petter | 0:6cf6e566c0da | 23 | serial.baud(115200); |
petter | 0:6cf6e566c0da | 24 | printf("Serial baudrate set\r\n"); |
petter | 0:6cf6e566c0da | 25 | } |
petter | 0:6cf6e566c0da | 26 | |
petter | 0:6cf6e566c0da | 27 | bool RN52::changed(){ |
petter | 0:6cf6e566c0da | 28 | static bool last = 0; |
petter | 0:6cf6e566c0da | 29 | if(last != event_pin) { |
petter | 0:6cf6e566c0da | 30 | last = event_pin; |
petter | 0:6cf6e566c0da | 31 | return !event_pin; |
petter | 0:6cf6e566c0da | 32 | } |
petter | 0:6cf6e566c0da | 33 | last = event_pin; |
petter | 0:6cf6e566c0da | 34 | return 0; |
petter | 0:6cf6e566c0da | 35 | } |
petter | 0:6cf6e566c0da | 36 | |
petter | 0:6cf6e566c0da | 37 | |
petter | 0:6cf6e566c0da | 38 | bool RN52::set(RN52_COMMAND cmd){ |
petter | 0:6cf6e566c0da | 39 | char response[40]; |
petter | 0:6cf6e566c0da | 40 | switch (cmd) { |
petter | 0:6cf6e566c0da | 41 | case RN52_PLAYPAUSE: |
petter | 0:6cf6e566c0da | 42 | serial.printf(PLAYPAUSE); |
petter | 0:6cf6e566c0da | 43 | break; |
petter | 0:6cf6e566c0da | 44 | case RN52_NEXTTRACK: |
petter | 0:6cf6e566c0da | 45 | serial.printf(NEXTTRACK); |
petter | 0:6cf6e566c0da | 46 | break; |
petter | 0:6cf6e566c0da | 47 | case RN52_PREVTRACK: |
petter | 0:6cf6e566c0da | 48 | serial.printf(PREVTRACK); |
petter | 0:6cf6e566c0da | 49 | break; |
petter | 0:6cf6e566c0da | 50 | case RN52_CONNECT: |
petter | 0:6cf6e566c0da | 51 | serial.printf(CONNECT); |
petter | 0:6cf6e566c0da | 52 | break; |
petter | 0:6cf6e566c0da | 53 | case RN52_DISCONNECT: |
petter | 0:6cf6e566c0da | 54 | serial.printf(DISCONNECT); |
petter | 0:6cf6e566c0da | 55 | break; |
petter | 0:6cf6e566c0da | 56 | case RN52_REBOOT: |
petter | 0:6cf6e566c0da | 57 | serial.printf(REBOOT); |
petter | 0:6cf6e566c0da | 58 | break; |
petter | 0:6cf6e566c0da | 59 | case RN52_VOLUMEUP: |
petter | 0:6cf6e566c0da | 60 | serial.printf(VOLUMEUP); |
petter | 0:6cf6e566c0da | 61 | break; |
petter | 0:6cf6e566c0da | 62 | case RN52_MAXVOLUME: |
petter | 0:6cf6e566c0da | 63 | serial.printf(MAXVOLUME); |
petter | 0:6cf6e566c0da | 64 | break; |
petter | 0:6cf6e566c0da | 65 | case RN52_ASSISTANT: |
petter | 0:6cf6e566c0da | 66 | serial.printf(ASSISTANT); |
petter | 0:6cf6e566c0da | 67 | break; |
petter | 0:6cf6e566c0da | 68 | default: |
petter | 0:6cf6e566c0da | 69 | return false; |
petter | 0:6cf6e566c0da | 70 | } |
petter | 0:6cf6e566c0da | 71 | capture_response(response); |
petter | 0:6cf6e566c0da | 72 | return (response[0] == 'A'); |
petter | 0:6cf6e566c0da | 73 | } |
petter | 0:6cf6e566c0da | 74 | |
petter | 0:6cf6e566c0da | 75 | bool RN52::get(RN52_COMMAND cmd, RN52_RESULT * result){ |
petter | 0:6cf6e566c0da | 76 | switch (cmd) { |
petter | 0:6cf6e566c0da | 77 | case RN52_GETSTATUS: |
petter | 0:6cf6e566c0da | 78 | serial.printf(GETSTATUS); |
petter | 0:6cf6e566c0da | 79 | capture_response(result->response); |
petter | 0:6cf6e566c0da | 80 | result->media_connected = (result->response[0] & (1 << 2)) >> 2; |
petter | 0:6cf6e566c0da | 81 | result->phone_connected = (result->response[0] & (1 << 3)) >> 23; |
petter | 0:6cf6e566c0da | 82 | result->connection = (RN52_CONNECTION)(result->response[0] & 0x0F); |
petter | 0:6cf6e566c0da | 83 | if((result->response[0] & (1 << 4)) >> 4) { |
petter | 0:6cf6e566c0da | 84 | result->event = RN52_CALLER_ID_EVENT; |
petter | 0:6cf6e566c0da | 85 | } |
petter | 0:6cf6e566c0da | 86 | else if((result->response[0] & (1 << 5)) >> 5) { |
petter | 0:6cf6e566c0da | 87 | result->event = RN52_TRACK_CHANGE_EVENT; |
petter | 0:6cf6e566c0da | 88 | } |
petter | 0:6cf6e566c0da | 89 | else { |
petter | 0:6cf6e566c0da | 90 | result->event = RN52_NO_EVENT; |
petter | 0:6cf6e566c0da | 91 | } |
petter | 0:6cf6e566c0da | 92 | break; |
petter | 0:6cf6e566c0da | 93 | case RN52_CALLER_ID: |
petter | 0:6cf6e566c0da | 94 | serial.printf(CALLER_ID); |
petter | 0:6cf6e566c0da | 95 | capture_response(result->response); |
petter | 0:6cf6e566c0da | 96 | //parse the response |
petter | 0:6cf6e566c0da | 97 | break; |
petter | 0:6cf6e566c0da | 98 | case RN52_TRACK_METADATA: |
petter | 0:6cf6e566c0da | 99 | serial.printf(TRACK_METADATA); |
petter | 0:6cf6e566c0da | 100 | capture_response(result->response); |
petter | 0:6cf6e566c0da | 101 | //parse the response |
petter | 0:6cf6e566c0da | 102 | default: |
petter | 0:6cf6e566c0da | 103 | return 0; |
petter | 0:6cf6e566c0da | 104 | } |
petter | 0:6cf6e566c0da | 105 | return 1; |
petter | 0:6cf6e566c0da | 106 | } |
petter | 0:6cf6e566c0da | 107 | |
petter | 0:6cf6e566c0da | 108 | |
petter | 0:6cf6e566c0da | 109 | void RN52::capture_response(char * str){ |
petter | 0:6cf6e566c0da | 110 | char c = ' '; |
petter | 0:6cf6e566c0da | 111 | char n = 0; |
petter | 0:6cf6e566c0da | 112 | while(c != '\n') { |
petter | 0:6cf6e566c0da | 113 | if(serial.readable()) { |
petter | 0:6cf6e566c0da | 114 | c = serial.getc(); |
petter | 0:6cf6e566c0da | 115 | str[n] = c; |
petter | 0:6cf6e566c0da | 116 | n++; |
petter | 0:6cf6e566c0da | 117 | } |
petter | 0:6cf6e566c0da | 118 | } |
petter | 0:6cf6e566c0da | 119 | str[n] = '\0'; |
petter | 0:6cf6e566c0da | 120 | } |