Sony's LANC camera control protocol project.

Dependencies:   aconno_LANC aconno_bsp aconno_SEGGER_RTT

Committer:
jurica238814
Date:
Fri Nov 17 11:10:29 2017 +0000
Revision:
8:3375dd304db9
Parent:
6:8cf24e946b0b
Child:
9:978106d4b181
Test version with LEDs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jurica238814 0:d616ca59aad8 1 /*
jurica238814 0:d616ca59aad8 2 * Example to demonstrate usage of the nrf52's I2S interface
jurica238814 0:d616ca59aad8 3 *
jurica238814 0:d616ca59aad8 4 * Made by Jurica Resetar @ aconno
jurica238814 0:d616ca59aad8 5 * jurica_resetar@yahoo.com
jurica238814 0:d616ca59aad8 6 * More info @ aconno.de
jurica238814 0:d616ca59aad8 7 *
jurica238814 0:d616ca59aad8 8 * All rights reserved
jurica238814 0:d616ca59aad8 9 *
jurica238814 0:d616ca59aad8 10 */
jurica238814 0:d616ca59aad8 11
jurica238814 0:d616ca59aad8 12 #include "mbed.h"
jurica238814 0:d616ca59aad8 13 #include "acd52832_bsp.h"
jurica238814 6:8cf24e946b0b 14 #include "ble/BLE.h"
jurica238814 6:8cf24e946b0b 15 #include "GapAdvertisingData.h"
jurica238814 6:8cf24e946b0b 16 #include "AckService.h"
jurica238814 0:d616ca59aad8 17
jurica238814 2:b28027b9c099 18 #define MY_BUF_SIZE 13*8
jurica238814 1:3e3dded8192f 19 #define LANC_H 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /* 13 B */
jurica238814 2:b28027b9c099 20 #define LANC_H_L 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF /* 13 B */
jurica238814 1:3e3dded8192f 21 #define LANC_L 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 13 B */
jurica238814 0:d616ca59aad8 22
jurica238814 0:d616ca59aad8 23 /*
jurica238814 0:d616ca59aad8 24 * Bitovi na I2S bus idu od MSBa do LSBa
jurica238814 0:d616ca59aad8 25 */
jurica238814 0:d616ca59aad8 26
jurica238814 2:b28027b9c099 27 #define LANC_COMMAND_PIN (p2) // Pin connected to Tr to pull lanc bus down/up 2/26
jurica238814 2:b28027b9c099 28 #define LANC_PIN (p3) // Lanc bus pin (to scan for START/STOP bits) 3/25
jurica238814 5:ecb7712b0825 29 #define LED_ON (0)
jurica238814 5:ecb7712b0825 30 #define LED_OFF (1)
jurica238814 6:8cf24e946b0b 31 #define MSD_SIZE (29) /* Manufacturer Specific Data lenght (in B) */
jurica238814 0:d616ca59aad8 32
jurica238814 6:8cf24e946b0b 33 uint8_t MSD[MSD_SIZE] = {0x59, 0x00, 0xDD, 0x4E, 0xCD, 0xC5, 0x5E, 0xA3, 0x43, 0x67, 0x8B, 0x84, 0x94, 0xFF, 0xBA, 0xD9, 0x29, 0xC6};
jurica238814 6:8cf24e946b0b 34 uint8_t myMacAddress[6] = {};
jurica238814 6:8cf24e946b0b 35 ACKService<1> *ackServicePtr;
jurica238814 6:8cf24e946b0b 36 BLE &ble = BLE::Instance();
jurica238814 6:8cf24e946b0b 37
jurica238814 6:8cf24e946b0b 38 void sendCommand(uint32_t *commandType, uint32_t *command);
jurica238814 6:8cf24e946b0b 39 GapAdvertisingData advData = GapAdvertisingData();
jurica238814 6:8cf24e946b0b 40
jurica238814 6:8cf24e946b0b 41 DigitalOut alive(p23);
jurica238814 6:8cf24e946b0b 42 DigitalOut connectedLED(p24);
jurica238814 8:3375dd304db9 43 DigitalOut testLED(p22);
jurica238814 2:b28027b9c099 44
jurica238814 2:b28027b9c099 45 uint8_t normalCommand[MY_BUF_SIZE] __attribute__ ((aligned (32))) = {LANC_L,LANC_L,LANC_L,LANC_H, LANC_H,LANC_L,LANC_L,LANC_L};
jurica238814 5:ecb7712b0825 46 uint8_t zoomCommand[MY_BUF_SIZE] __attribute__ ((aligned (32))) = {LANC_L,LANC_L,LANC_L,LANC_H, LANC_L,LANC_H,LANC_L,LANC_L};
jurica238814 2:b28027b9c099 47 uint8_t startStop[MY_BUF_SIZE] __attribute__ ((aligned (32))) = {LANC_H,LANC_H,LANC_L,LANC_L,LANC_H,LANC_H,LANC_L,LANC_L};
jurica238814 4:6560e2966186 48 uint8_t zoomIn[MY_BUF_SIZE] __attribute__ ((aligned (32))) = {LANC_H,LANC_L,LANC_L,LANC_H,LANC_H,LANC_H,LANC_L,LANC_L}; // Tele
jurica238814 4:6560e2966186 49 uint8_t zoomOut[MY_BUF_SIZE] __attribute__ ((aligned (32))) = {LANC_H,LANC_H,LANC_L,LANC_H,LANC_H,LANC_H,LANC_L,LANC_L}; // Wide
jurica238814 1:3e3dded8192f 50
jurica238814 5:ecb7712b0825 51 uint32_t *normalCmdAddr = (uint32_t*)normalCommand;
jurica238814 5:ecb7712b0825 52 uint32_t *zoomCmdAddr = (uint32_t*)zoomCommand;
jurica238814 5:ecb7712b0825 53 uint32_t *startStopAddr = (uint32_t*)startStop;
jurica238814 5:ecb7712b0825 54 uint32_t *zoomInAddr = (uint32_t*)zoomIn;
jurica238814 5:ecb7712b0825 55 uint32_t *zoomOutAddr = (uint32_t*)zoomOut;
jurica238814 2:b28027b9c099 56
jurica238814 5:ecb7712b0825 57 uint8_t volatile i2sFlag = 0;
jurica238814 4:6560e2966186 58 uint8_t state = 0; /* 1 -> Send command type, 0 -> send command */
jurica238814 6:8cf24e946b0b 59
jurica238814 1:3e3dded8192f 60 InterruptIn button(LANC_PIN);
jurica238814 2:b28027b9c099 61 Timer frameTimer;
jurica238814 1:3e3dded8192f 62
jurica238814 6:8cf24e946b0b 63 void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params){
jurica238814 8:3375dd304db9 64 //connectedLED = LED_ON;
jurica238814 6:8cf24e946b0b 65 ble.gap().stopAdvertising();
jurica238814 6:8cf24e946b0b 66 }
jurica238814 6:8cf24e946b0b 67
jurica238814 6:8cf24e946b0b 68 void onDataWrittenCallback(const GattWriteCallbackParams *params) {
jurica238814 6:8cf24e946b0b 69 //newImage[cnt] = params->data[i];
jurica238814 6:8cf24e946b0b 70 switch(params->data[0]){
jurica238814 6:8cf24e946b0b 71 case 0x00:{
jurica238814 8:3375dd304db9 72 //sendCommand(normalCmdAddr, startStopAddr);
jurica238814 8:3375dd304db9 73 alive = !alive;
jurica238814 8:3375dd304db9 74
jurica238814 6:8cf24e946b0b 75 break;
jurica238814 6:8cf24e946b0b 76 }
jurica238814 6:8cf24e946b0b 77 case 0x01:{
jurica238814 8:3375dd304db9 78 //sendCommand(zoomCmdAddr, zoomOutAddr);
jurica238814 8:3375dd304db9 79 connectedLED = !connectedLED;
jurica238814 8:3375dd304db9 80
jurica238814 6:8cf24e946b0b 81 break;
jurica238814 6:8cf24e946b0b 82 }
jurica238814 6:8cf24e946b0b 83 case 0x02:{
jurica238814 8:3375dd304db9 84 //sendCommand(zoomCmdAddr, zoomInAddr);
jurica238814 8:3375dd304db9 85 testLED = !testLED;
jurica238814 6:8cf24e946b0b 86 break;
jurica238814 6:8cf24e946b0b 87 }
jurica238814 6:8cf24e946b0b 88 default: break;
jurica238814 6:8cf24e946b0b 89 }
jurica238814 6:8cf24e946b0b 90 return;
jurica238814 6:8cf24e946b0b 91 }
jurica238814 6:8cf24e946b0b 92
jurica238814 6:8cf24e946b0b 93 /**
jurica238814 6:8cf24e946b0b 94 * Restart Advertising on disconnection
jurica238814 6:8cf24e946b0b 95 */
jurica238814 6:8cf24e946b0b 96 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){
jurica238814 6:8cf24e946b0b 97 connectedLED = LED_OFF;
jurica238814 6:8cf24e946b0b 98 BLE::Instance().gap().startAdvertising();
jurica238814 6:8cf24e946b0b 99 }
jurica238814 6:8cf24e946b0b 100
jurica238814 6:8cf24e946b0b 101
jurica238814 6:8cf24e946b0b 102 /**
jurica238814 6:8cf24e946b0b 103 * This function is called when the ble initialization process has failed
jurica238814 6:8cf24e946b0b 104 */
jurica238814 6:8cf24e946b0b 105 void onBleInitError(BLE &ble, ble_error_t error){
jurica238814 6:8cf24e946b0b 106 /* Avoid compiler warnings */
jurica238814 6:8cf24e946b0b 107 (void) ble;
jurica238814 6:8cf24e946b0b 108 (void) error;
jurica238814 6:8cf24e946b0b 109 /* Initialization error handling should go here */
jurica238814 6:8cf24e946b0b 110 }
jurica238814 6:8cf24e946b0b 111
jurica238814 6:8cf24e946b0b 112 /**
jurica238814 6:8cf24e946b0b 113 * Callback triggered when the ble initialization process has finished
jurica238814 6:8cf24e946b0b 114 */
jurica238814 6:8cf24e946b0b 115 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params){
jurica238814 6:8cf24e946b0b 116 BLE& ble = params->ble;
jurica238814 6:8cf24e946b0b 117 uint8_t init_values[1];
jurica238814 6:8cf24e946b0b 118
jurica238814 6:8cf24e946b0b 119
jurica238814 6:8cf24e946b0b 120 /* Get my MAC address */
jurica238814 6:8cf24e946b0b 121 BLEProtocol::AddressType_t temp_address_type;
jurica238814 6:8cf24e946b0b 122 ble.gap().getAddress(&temp_address_type, myMacAddress);
jurica238814 6:8cf24e946b0b 123 ackServicePtr = new ACKService<1>(ble, init_values);
jurica238814 6:8cf24e946b0b 124
jurica238814 6:8cf24e946b0b 125 ble.gap().onDisconnection(disconnectionCallback);
jurica238814 6:8cf24e946b0b 126 ble.gap().onConnection(onConnectionCallback);
jurica238814 6:8cf24e946b0b 127 ble.gattServer().onDataWritten(onDataWrittenCallback);
jurica238814 6:8cf24e946b0b 128
jurica238814 6:8cf24e946b0b 129 /* setup advertising */
jurica238814 6:8cf24e946b0b 130 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)MSD, MSD_SIZE);
jurica238814 6:8cf24e946b0b 131 ble.gap().setAdvertisingInterval(500); // --> Has to be at least 100ms!
jurica238814 6:8cf24e946b0b 132 ble.gap().startAdvertising();
jurica238814 6:8cf24e946b0b 133 }
jurica238814 6:8cf24e946b0b 134
jurica238814 5:ecb7712b0825 135 void i2sReady(){
jurica238814 5:ecb7712b0825 136 /* Interrupt handler */
jurica238814 5:ecb7712b0825 137 i2sFlag = 1;
jurica238814 5:ecb7712b0825 138 }
jurica238814 0:d616ca59aad8 139
jurica238814 5:ecb7712b0825 140 uint8_t waitForStartBit(){
jurica238814 5:ecb7712b0825 141 static uint8_t firstInt = 1;
jurica238814 3:eb5b87baf6cf 142 static int lastIntTime_us = 0;
jurica238814 1:3e3dded8192f 143
jurica238814 5:ecb7712b0825 144 while(!i2sFlag); // Wait for the interrupt to change the flag
jurica238814 5:ecb7712b0825 145 if(firstInt){
jurica238814 5:ecb7712b0825 146 firstInt = 0;
jurica238814 5:ecb7712b0825 147 frameTimer.start();
jurica238814 5:ecb7712b0825 148 }
jurica238814 5:ecb7712b0825 149 lastIntTime_us = frameTimer.read_us();
jurica238814 5:ecb7712b0825 150 frameTimer.reset();
jurica238814 5:ecb7712b0825 151 i2sFlag = 0;
jurica238814 5:ecb7712b0825 152
jurica238814 5:ecb7712b0825 153 if(lastIntTime_us > 10000){
jurica238814 5:ecb7712b0825 154 return 1;
jurica238814 5:ecb7712b0825 155 }
jurica238814 5:ecb7712b0825 156 else{
jurica238814 5:ecb7712b0825 157 return 0;
jurica238814 5:ecb7712b0825 158 }
jurica238814 5:ecb7712b0825 159 }
jurica238814 5:ecb7712b0825 160
jurica238814 5:ecb7712b0825 161 void sendi2sData(){
jurica238814 5:ecb7712b0825 162 NRF_I2S->EVENTS_TXPTRUPD = 0;
jurica238814 5:ecb7712b0825 163 NRF_I2S->ENABLE = 1;
jurica238814 5:ecb7712b0825 164 NRF_I2S->TASKS_START = 1;
jurica238814 5:ecb7712b0825 165
jurica238814 5:ecb7712b0825 166 while(!NRF_I2S->EVENTS_TXPTRUPD); // Wait for the data to be send
jurica238814 5:ecb7712b0825 167 NRF_I2S->EVENTS_TXPTRUPD = 0;
jurica238814 5:ecb7712b0825 168 while(!NRF_I2S->EVENTS_TXPTRUPD); // Wait for the data to be send
jurica238814 5:ecb7712b0825 169 NRF_I2S->EVENTS_TXPTRUPD = 0;
jurica238814 5:ecb7712b0825 170 NRF_I2S->TASKS_STOP = 1;
jurica238814 5:ecb7712b0825 171 while(!NRF_I2S->EVENTS_STOPPED);
jurica238814 5:ecb7712b0825 172 NRF_I2S->ENABLE = 0;
jurica238814 5:ecb7712b0825 173 }
jurica238814 5:ecb7712b0825 174
jurica238814 5:ecb7712b0825 175 void sendCommand(uint32_t *commandType, uint32_t *command){
jurica238814 5:ecb7712b0825 176
jurica238814 5:ecb7712b0825 177
jurica238814 2:b28027b9c099 178 /*
jurica238814 2:b28027b9c099 179 * Na prvi interrupt pokreni frameTimer.
jurica238814 2:b28027b9c099 180 * Na svaki interrupt (falling edge na Lanc busu) izmjeri vrijeme od zadnjeg eventa
jurica238814 2:b28027b9c099 181 * Ako je to vrijeme > 5ms, onda je upravo taj prekid izazvao start bit novog framea
jurica238814 2:b28027b9c099 182 * U tom slučaju, kreni s donjim kodom, inaće nemoj ništa slati
jurica238814 2:b28027b9c099 183 */
jurica238814 5:ecb7712b0825 184 uint8_t cnt = 0;
jurica238814 2:b28027b9c099 185
jurica238814 5:ecb7712b0825 186 for(cnt; cnt < 4; cnt++){
jurica238814 5:ecb7712b0825 187 while(!(waitForStartBit()));
jurica238814 5:ecb7712b0825 188 NRF_I2S->TXD.PTR = (uint32_t)commandType;
jurica238814 5:ecb7712b0825 189 __disable_irq();
jurica238814 5:ecb7712b0825 190 // First or second start bit
jurica238814 5:ecb7712b0825 191 wait_us(60); // Small delay for first bit after start bit
jurica238814 5:ecb7712b0825 192 sendi2sData();
jurica238814 5:ecb7712b0825 193 __enable_irq();
jurica238814 5:ecb7712b0825 194 i2sFlag = 0;
jurica238814 2:b28027b9c099 195
jurica238814 5:ecb7712b0825 196 while(!i2sFlag); // Wait for new start bit (second byte into frame)
jurica238814 2:b28027b9c099 197
jurica238814 5:ecb7712b0825 198 NRF_I2S->TXD.PTR = (uint32_t)command;
jurica238814 5:ecb7712b0825 199 __disable_irq();
jurica238814 5:ecb7712b0825 200 // First or second start bit
jurica238814 5:ecb7712b0825 201 wait_us(60); // Small delay for first bit after start bit
jurica238814 5:ecb7712b0825 202 sendi2sData();
jurica238814 5:ecb7712b0825 203 i2sFlag = 0;
jurica238814 5:ecb7712b0825 204 __enable_irq();
jurica238814 2:b28027b9c099 205 }
jurica238814 1:3e3dded8192f 206 }
jurica238814 1:3e3dded8192f 207
jurica238814 5:ecb7712b0825 208 void i2sInit(){
jurica238814 0:d616ca59aad8 209 NRF_I2S->CONFIG.RXEN = 0; // Disable reception
jurica238814 0:d616ca59aad8 210 NRF_I2S->CONFIG.MCKEN = 1; // Enable MCK generator
jurica238814 4:6560e2966186 211
jurica238814 1:3e3dded8192f 212 NRF_I2S->CONFIG.MCKFREQ = 0x10000000; // DIV 31
jurica238814 1:3e3dded8192f 213 NRF_I2S->CONFIG.RATIO = 0; // Ratio = 32x
jurica238814 0:d616ca59aad8 214
jurica238814 1:3e3dded8192f 215 NRF_I2S->CONFIG.SWIDTH = 0; // Sample width = 8 bit
jurica238814 1:3e3dded8192f 216 NRF_I2S->CONFIG.ALIGN = 0; // Alignment = Right
jurica238814 0:d616ca59aad8 217 NRF_I2S->CONFIG.FORMAT = 0; // Format = I2S
jurica238814 0:d616ca59aad8 218 NRF_I2S->CONFIG.CHANNELS = 0; // Use stereo
jurica238814 0:d616ca59aad8 219
jurica238814 1:3e3dded8192f 220 NRF_I2S->PSEL.LRCK = 27; // LRCK routed to pin 26
jurica238814 1:3e3dded8192f 221 NRF_I2S->PSEL.SDOUT = LANC_COMMAND_PIN; // SDOUT routed to pin 28
jurica238814 1:3e3dded8192f 222 NRF_I2S->PSEL.SCK = 30; // SCK routed to pin 30
jurica238814 1:3e3dded8192f 223 NRF_I2S->PSEL.MCK = 0x80000000; // MCK disconnected
jurica238814 1:3e3dded8192f 224 NRF_I2S->PSEL.SDIN = 0x80000000; // SDIN disconnected
jurica238814 0:d616ca59aad8 225
jurica238814 2:b28027b9c099 226 NRF_I2S->TXD.PTR = (uint32_t)normalCmdAddr;
jurica238814 2:b28027b9c099 227 NRF_I2S->RXTXD.MAXCNT = MY_BUF_SIZE/4; // Div with 4 cuz that's number of 32 bit words
jurica238814 0:d616ca59aad8 228 }
jurica238814 0:d616ca59aad8 229
jurica238814 0:d616ca59aad8 230
jurica238814 5:ecb7712b0825 231 int main(void){
jurica238814 8:3375dd304db9 232 alive = LED_OFF;
jurica238814 5:ecb7712b0825 233
jurica238814 6:8cf24e946b0b 234 ble.init(bleInitComplete);
jurica238814 6:8cf24e946b0b 235 while (ble.hasInitialized() == false) { /* spin loop */ }
jurica238814 6:8cf24e946b0b 236 ble.gap().startAdvertising();
jurica238814 5:ecb7712b0825 237
jurica238814 6:8cf24e946b0b 238 i2sInit();
jurica238814 5:ecb7712b0825 239 button.fall(i2sReady);
jurica238814 5:ecb7712b0825 240
jurica238814 8:3375dd304db9 241 //sendCommand(zoomCmdAddr, zoomInAddr);
jurica238814 8:3375dd304db9 242
jurica238814 8:3375dd304db9 243 connectedLED = LED_OFF;
jurica238814 8:3375dd304db9 244 testLED = LED_OFF;
jurica238814 6:8cf24e946b0b 245
jurica238814 5:ecb7712b0825 246 while(1){
jurica238814 6:8cf24e946b0b 247 ble.waitForEvent();
jurica238814 5:ecb7712b0825 248 }
jurica238814 5:ecb7712b0825 249 }