Sony's LANC camera control protocol project.

Dependencies:   aconno_LANC aconno_bsp aconno_SEGGER_RTT

main.cpp

Committer:
jurica238814
Date:
2017-11-01
Revision:
5:ecb7712b0825
Parent:
4:6560e2966186
Child:
6:8cf24e946b0b

File content as of revision 5:ecb7712b0825:

/*
 * 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"

#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)

DigitalOut alive(p24);

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 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 = 0;
    
    i2sInit();
    
    button.fall(i2sReady);
    
    while(1){
        sendCommand(zoomCmdAddr, zoomInAddr);
        sendCommand(zoomCmdAddr, zoomInAddr);
        sendCommand(zoomCmdAddr, zoomInAddr);
        sendCommand(zoomCmdAddr, zoomInAddr);
        sendCommand(zoomCmdAddr, zoomInAddr);
        sendCommand(zoomCmdAddr, zoomInAddr);
        sendCommand(zoomCmdAddr, zoomInAddr);
        sendCommand(zoomCmdAddr, zoomInAddr);
        wait_ms(350);
        sendCommand(zoomCmdAddr, zoomOutAddr);
        sendCommand(zoomCmdAddr, zoomOutAddr);
        sendCommand(zoomCmdAddr, zoomOutAddr);
        sendCommand(zoomCmdAddr, zoomOutAddr);
        sendCommand(zoomCmdAddr, zoomOutAddr);
        sendCommand(zoomCmdAddr, zoomOutAddr);
        sendCommand(zoomCmdAddr, zoomOutAddr);
        sendCommand(zoomCmdAddr, zoomOutAddr);
        wait_ms(350);
    }
}