Sony's LANC camera control protocol project.
Dependencies: aconno_LANC aconno_bsp aconno_SEGGER_RTT
main.cpp
- Committer:
- jurica238814
- Date:
- 2017-11-17
- Revision:
- 8:3375dd304db9
- Parent:
- 6:8cf24e946b0b
- Child:
- 9:978106d4b181
File content as of revision 8:3375dd304db9:
/* * Example to demonstrate usage of the nrf52's I2S interface * * Made by Jurica Resetar @ aconno * jurica_resetar@yahoo.com * More info @ aconno.de * * All rights reserved * */ #include "mbed.h" #include "acd52832_bsp.h" #include "ble/BLE.h" #include "GapAdvertisingData.h" #include "AckService.h" #define MY_BUF_SIZE 13*8 #define LANC_H 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /* 13 B */ #define LANC_H_L 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF /* 13 B */ #define LANC_L 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 13 B */ /* * Bitovi na I2S bus idu od MSBa do LSBa */ #define LANC_COMMAND_PIN (p2) // Pin connected to Tr to pull lanc bus down/up 2/26 #define LANC_PIN (p3) // Lanc bus pin (to scan for START/STOP bits) 3/25 #define LED_ON (0) #define LED_OFF (1) #define MSD_SIZE (29) /* Manufacturer Specific Data lenght (in B) */ uint8_t MSD[MSD_SIZE] = {0x59, 0x00, 0xDD, 0x4E, 0xCD, 0xC5, 0x5E, 0xA3, 0x43, 0x67, 0x8B, 0x84, 0x94, 0xFF, 0xBA, 0xD9, 0x29, 0xC6}; uint8_t myMacAddress[6] = {}; ACKService<1> *ackServicePtr; BLE &ble = BLE::Instance(); void sendCommand(uint32_t *commandType, uint32_t *command); GapAdvertisingData advData = GapAdvertisingData(); DigitalOut alive(p23); DigitalOut connectedLED(p24); DigitalOut testLED(p22); 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}; 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}; 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}; 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 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 uint32_t *normalCmdAddr = (uint32_t*)normalCommand; uint32_t *zoomCmdAddr = (uint32_t*)zoomCommand; uint32_t *startStopAddr = (uint32_t*)startStop; uint32_t *zoomInAddr = (uint32_t*)zoomIn; uint32_t *zoomOutAddr = (uint32_t*)zoomOut; uint8_t volatile i2sFlag = 0; uint8_t state = 0; /* 1 -> Send command type, 0 -> send command */ InterruptIn button(LANC_PIN); Timer frameTimer; void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params){ //connectedLED = LED_ON; ble.gap().stopAdvertising(); } void onDataWrittenCallback(const GattWriteCallbackParams *params) { //newImage[cnt] = params->data[i]; switch(params->data[0]){ case 0x00:{ //sendCommand(normalCmdAddr, startStopAddr); alive = !alive; break; } case 0x01:{ //sendCommand(zoomCmdAddr, zoomOutAddr); connectedLED = !connectedLED; break; } case 0x02:{ //sendCommand(zoomCmdAddr, zoomInAddr); testLED = !testLED; break; } default: break; } return; } /** * Restart Advertising on disconnection */ void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ connectedLED = LED_OFF; BLE::Instance().gap().startAdvertising(); } /** * This function is called when the ble initialization process has failed */ void onBleInitError(BLE &ble, ble_error_t error){ /* Avoid compiler warnings */ (void) ble; (void) error; /* Initialization error handling should go here */ } /** * Callback triggered when the ble initialization process has finished */ void bleInitComplete(BLE::InitializationCompleteCallbackContext *params){ BLE& ble = params->ble; uint8_t init_values[1]; /* Get my MAC address */ BLEProtocol::AddressType_t temp_address_type; ble.gap().getAddress(&temp_address_type, myMacAddress); ackServicePtr = new ACKService<1>(ble, init_values); ble.gap().onDisconnection(disconnectionCallback); ble.gap().onConnection(onConnectionCallback); ble.gattServer().onDataWritten(onDataWrittenCallback); /* setup advertising */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)MSD, MSD_SIZE); ble.gap().setAdvertisingInterval(500); // --> Has to be at least 100ms! ble.gap().startAdvertising(); } void i2sReady(){ /* Interrupt handler */ i2sFlag = 1; } uint8_t waitForStartBit(){ static uint8_t firstInt = 1; static int lastIntTime_us = 0; while(!i2sFlag); // Wait for the interrupt to change the flag if(firstInt){ firstInt = 0; frameTimer.start(); } lastIntTime_us = frameTimer.read_us(); frameTimer.reset(); i2sFlag = 0; if(lastIntTime_us > 10000){ return 1; } else{ return 0; } } void sendi2sData(){ NRF_I2S->EVENTS_TXPTRUPD = 0; NRF_I2S->ENABLE = 1; NRF_I2S->TASKS_START = 1; while(!NRF_I2S->EVENTS_TXPTRUPD); // Wait for the data to be send NRF_I2S->EVENTS_TXPTRUPD = 0; while(!NRF_I2S->EVENTS_TXPTRUPD); // Wait for the data to be send NRF_I2S->EVENTS_TXPTRUPD = 0; NRF_I2S->TASKS_STOP = 1; while(!NRF_I2S->EVENTS_STOPPED); NRF_I2S->ENABLE = 0; } void sendCommand(uint32_t *commandType, uint32_t *command){ /* * Na prvi interrupt pokreni frameTimer. * Na svaki interrupt (falling edge na Lanc busu) izmjeri vrijeme od zadnjeg eventa * Ako je to vrijeme > 5ms, onda je upravo taj prekid izazvao start bit novog framea * U tom slučaju, kreni s donjim kodom, inaće nemoj ništa slati */ uint8_t cnt = 0; for(cnt; cnt < 4; cnt++){ while(!(waitForStartBit())); NRF_I2S->TXD.PTR = (uint32_t)commandType; __disable_irq(); // First or second start bit wait_us(60); // Small delay for first bit after start bit sendi2sData(); __enable_irq(); i2sFlag = 0; while(!i2sFlag); // Wait for new start bit (second byte into frame) NRF_I2S->TXD.PTR = (uint32_t)command; __disable_irq(); // First or second start bit wait_us(60); // Small delay for first bit after start bit sendi2sData(); i2sFlag = 0; __enable_irq(); } } void i2sInit(){ NRF_I2S->CONFIG.RXEN = 0; // Disable reception NRF_I2S->CONFIG.MCKEN = 1; // Enable MCK generator NRF_I2S->CONFIG.MCKFREQ = 0x10000000; // DIV 31 NRF_I2S->CONFIG.RATIO = 0; // Ratio = 32x NRF_I2S->CONFIG.SWIDTH = 0; // Sample width = 8 bit NRF_I2S->CONFIG.ALIGN = 0; // Alignment = Right NRF_I2S->CONFIG.FORMAT = 0; // Format = I2S NRF_I2S->CONFIG.CHANNELS = 0; // Use stereo NRF_I2S->PSEL.LRCK = 27; // LRCK routed to pin 26 NRF_I2S->PSEL.SDOUT = LANC_COMMAND_PIN; // SDOUT routed to pin 28 NRF_I2S->PSEL.SCK = 30; // SCK routed to pin 30 NRF_I2S->PSEL.MCK = 0x80000000; // MCK disconnected NRF_I2S->PSEL.SDIN = 0x80000000; // SDIN disconnected NRF_I2S->TXD.PTR = (uint32_t)normalCmdAddr; NRF_I2S->RXTXD.MAXCNT = MY_BUF_SIZE/4; // Div with 4 cuz that's number of 32 bit words } int main(void){ alive = LED_OFF; ble.init(bleInitComplete); while (ble.hasInitialized() == false) { /* spin loop */ } ble.gap().startAdvertising(); i2sInit(); button.fall(i2sReady); //sendCommand(zoomCmdAddr, zoomInAddr); connectedLED = LED_OFF; testLED = LED_OFF; while(1){ ble.waitForEvent(); } }