Sony's LANC camera control protocol project.
Dependencies: aconno_LANC aconno_bsp aconno_SEGGER_RTT
main.cpp
- Committer:
- jurica238814
- Date:
- 2018-08-28
- Revision:
- 12:69dbd9ef58e8
- Parent:
- 11:e5f11b96088e
File content as of revision 12:69dbd9ef58e8:
/*
* 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 PRINT_ON_RTT (1)
#ifdef PRINT_ON_RTT
#include "SEGGER_RTT.h"
#define printf(...) SEGGER_RTT_printf(0, __VA_ARGS__)
#else
#define printf(...)
#endif
#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<2> *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) {
/*
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;
}
*/
uint32_t commandType[MY_BUF_SIZE];
uint32_t command[MY_BUF_SIZE];
uint8_t counter;
printf("Data[0]: %d\n", params->data[0]);
printf("Data[1]: %d\n", params->data[1]);
for(counter = 0; counter < 8; counter++)
{
(params->data[0] & (1 << 7 - counter)) ? commandType[counter] = LANC_H :
commandType[counter] = LANC_L;
}
for(counter = 0; counter < 8; counter++)
{
(params->data[0] & (1 << 7 - counter)) ? command[counter] = LANC_H :
command[counter] = LANC_L;
}
sendCommand(commandType, command);
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[2];
/* Get my MAC address */
BLEProtocol::AddressType_t temp_address_type;
ble.gap().getAddress(&temp_address_type, myMacAddress);
ackServicePtr = new ACKService<2>(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();
}
}