同時公開のFunctionGenerator-BLEと同時利用によりファンクション・ジェネレータを実現する。

Dependencies:   mbed

FunctionGenerator-BLE

/users/ohneta/code/FunctionGenerator-BLE

what's this ? / 概要

あとで、もっとちゃんと書く(とおもう)

同時公開のFunctionGenerator-BLEと同時利用によりmbed LPC1768を使って、ファンクション・ジェネレータを実現する。

detail / 詳細

あとで、もっとちゃんと書く(とおもう)

FunctionGenerator-BLEはI2Cで所定のフォーマットに従ったデータをDACから出力する。

DACは連続するデータを出力し、任意の波形を出力する。

BLE command format / BLEコマンドフォーマット

あとで、ちゃんと書く(とおもう)

BLE App for iPhone

iOS用アプリソースコード App source codes for iOS

https://github.com/ohneta/FuncGenBLE

pictures / とりあえず写真など

外観

/media/uploads/ohneta/img_5614.jpg

アプリ画面

/media/uploads/ohneta/img_0006.png /media/uploads/ohneta/img_0007.png

出力波形

/media/uploads/ohneta/img_5616.jpg /media/uploads/ohneta/img_5615.jpg

more pictures...

main.cpp

Committer:
ohneta
Date:
2015-06-16
Revision:
0:cbf811b45305

File content as of revision 0:cbf811b45305:

#include "mbed.h"
#include <I2CSlave.h>
#include "FunctionGenCommands.h"


extern "C" void mbed_reset();

#define     PI      3.141592

#define     WAVE_MASTER_BUFFER_SIZE     360

#define     WAVE_READ_BUFFER_SIZE             (1024 * 8)
//#define     WAVE_READ_BUFFER_SIZE_FORCE       (1024 * 16 - 1)

#define     I2C_PACKET_LENGTH   36

#define     ONE_CLOCK_TIME      ((1.0 / 3.0) / (1000.0 * 1000.0))
//-----------------------------------------------------------------------

void initMasterWaveBuffer();
void masterToReadBufferByFreq(uint32_t paramFreq);
void clickedUpButton();
void clickedDownButton();
//void lookForYou();
void doCommand(char *readBuffer, int length);
void commandPrint(FGPacket *fgPacket);

//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//BusOut myleds(LED1, LED2, LED3, LED4);
//BusOut ladderDacBusOut(p21, p22, p23, p24, p25, p26, p5, p6, p7, p8);

DigitalOut  led1(LED1);     // I2C I/O
DigitalOut  led2(LED2);
DigitalOut  led3(LED3);     // ERROR
DigitalOut  led4(LED4);     // watch dog 

PortOut ladderDacPortOut(Port0, 0x00000001);
    // P0_0のみ有効 = p9

AnalogOut aout(p18);
InterruptIn upButton(p11);
InterruptIn downButton(p12);

//InterruptIn i2cStart(p13);
InterruptIn i2cStart(p29);
I2CSlave i2cSlave(p28, p27);
int gLookI2C = false;

Serial pc(USBTX, USBRX);

//-----------------------------------------------------------------------
uint32_t    gMasterFrequency = 366;
uint32_t    gLastFrequency = 366;

uint16_t gMasterBuffer[WAVE_MASTER_BUFFER_SIZE];
//uint16_t gReadBuffer[WAVE_READ_BUFFER_SIZE];
uint16_t gReadBuffer[WAVE_READ_BUFFER_SIZE] __attribute__((section("AHBSRAM0")));
uint16_t gReadBuffer_tmp[WAVE_READ_BUFFER_SIZE] __attribute__((section("AHBSRAM1")));
volatile int gReadBufferLength = 0;

char  gI2cReadBuffer[I2C_PACKET_LENGTH];   

WaveformInfo    gWaveformInfo;



//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

void initMasterWaveBuffer()
{
    // sin-wave
    for (int i = 0; i < WAVE_MASTER_BUFFER_SIZE; i++) {
        double rad = ((double)i / WAVE_MASTER_BUFFER_SIZE) * (PI * 2);   // = 0...2*PI
        double sinA = sin(rad); // answer: -1.0 〜 1.0
        gMasterBuffer[i] = (unsigned short)((sinA + 1.0) / 2.0 * 0xffff);
    }
    
    gMasterFrequency = 1.0 / (ONE_CLOCK_TIME * WAVE_MASTER_BUFFER_SIZE);
}

void masterToReadBufferByFreq(uint32_t paramFreq)
{
    gMasterFrequency = paramFreq;
    gLastFrequency = gMasterFrequency;
    
    gReadBufferLength = (1.0 / (paramFreq * ONE_CLOCK_TIME));
        // 2 <= gReadBufferLength <= WAVE_READ_BUFFER_SIZE

    double x = (double)WAVE_MASTER_BUFFER_SIZE / (double)gReadBufferLength;
    //double x = (double)WAVE_READ_BUFFER_SIZE_FORCE / (double)gReadBufferLength;

    pc.printf("gReadBufferLength: %d\n", gReadBufferLength);
    pc.printf("x: %f\n", x);

    for (int i = 0; i < gReadBufferLength; i++) {
        int pt = (int)((double)i * x);
        gReadBuffer[i] = gMasterBuffer[pt] & 0xffc0;
        //gReadBuffer[i] = (i & 0x01) ? 0xffff : 0x0000;
    }
}

void clearReadBuffer()
{
    for (int i = 0; i < WAVE_READ_BUFFER_SIZE; i++) {
    //for (int i = 0; i < WAVE_READ_BUFFER_SIZE_FORCE; i++) {
        gReadBuffer[i] = 0x0000;
    }
}

//-----------------------------------------------------------------------
#if 0
void clickedUpButton()
{
    upButton.disable_irq();
    downButton.disable_irq();
    wait(0.01);
    if (upButton == 1) {
        gInterruptCount++;
        if (gInterruptCount >= WAVE_READ_BUFFER_SIZE) {
            gInterruptCount = WAVE_READ_BUFFER_SIZE - 1;
        }
        masterToReadBuffer();
        //myleds = gInterruptCount;
    }
    upButton.enable_irq();
    downButton.enable_irq();
    
    //pc.printf("Interrupt Count: %d \n", gInterruptCount);
}

void clickedDownButton()
{
    upButton.disable_irq();
    downButton.disable_irq();
    wait(0.01);
    if (downButton == 1) {
        gInterruptCount--;
        if (gInterruptCount < 0) {
            gInterruptCount = 0;
        }
        masterToReadBuffer();
        //myleds = gInterruptCount;
    }
    upButton.enable_irq();
    downButton.enable_irq();

    //pc.printf("Interrupt Count: %d \n", gInterruptCount);
}
#endif
//-----------------------------------------------------------------------
/**
 *
 */
void i2cSlaveAction()
{
    pc.printf("--------\n");
    pc.printf("i2cSlaveAction()\n");

    static int cnt = 0;

    for (int i = 0; i < I2C_PACKET_LENGTH; i++) {
        gI2cReadBuffer[i] = 0x00;
    }

    int loopCount = 0;
    int result = i2cSlave.receive();
    while (result == I2CSlave::NoData) {
        wait_ms(10);
        result = i2cSlave.receive();
        if (loopCount > 100) {
            return;
        }
    }

    switch (result) {
        case I2CSlave::NoData:
            break;

        case I2CSlave::WriteGeneral:        //  the master is writing to all slave -- broadcast
            break;

        case I2CSlave::WriteAddressed:      // the master is writing to this slave
            int ret = i2cSlave.read(gI2cReadBuffer, I2C_PACKET_LENGTH);
            FGPacket *fgPacket = (FGPacket *)gI2cReadBuffer;

            pc.printf("Read : ret=%d  [ ", ret);
            for (int i = 0; i < fgPacket->header.length; i++) {
                pc.printf("%02x ", gI2cReadBuffer[i]);
            }
            pc.printf("]\n");

            doCommand(gI2cReadBuffer, I2C_PACKET_LENGTH);
            break;

        case I2CSlave::ReadAddressed:       //  the master has requested a read from this slave
            char buf[32];
            sprintf(buf, "Ooops:%d", cnt);
            i2cSlave.write(buf, strlen(buf));
            cnt++;
            break;

        default:
            break;
    }
}

void doCommand(char *readBuffer, int length)
{
    FGPacket *fgPacket = (FGPacket *)gI2cReadBuffer;
    commandPrint(fgPacket);

    switch (fgPacket->header.command) {
        // for Command
        case FGCommand_Non:
            break;

        case FGCommand_Device:
            // reserved for future.
            // fgPacket->body.commandDevice.device
            break;

        case FGCommand_Output:
            if (fgPacket->body.commandOutput.on == 0) {
                aout.write_u16(0x0000);
                clearReadBuffer();
            } else {
                masterToReadBufferByFreq(gMasterFrequency);
            }
            break;

        case FGCommand_Frequency:
            // TODO: 正確な周波数計算をすること!
            masterToReadBufferByFreq(fgPacket->body.commandFrequency.frequency);
            break;

        case FGCommand_WaveformInfo:
            // TODO: パラメタの内容をチェックすること!
            gWaveformInfo = fgPacket->body.commandWaveformInfo;

            break;
        case FGCommand_WaveformBlock:
            // TODO: パラメタの内容をチェックすること!
            uint32_t waveformOffset = fgPacket->body.commandWaveformBlock.blockNo * gWaveformInfo.blockSize;
            memcpy((uint8_t *)gMasterBuffer + waveformOffset, fgPacket->body.commandWaveformBlock.buffer, fgPacket->body.commandWaveformBlock.length);
            break;

        case FGCommand_WaveformToBuffer:
            masterToReadBufferByFreq(gMasterFrequency);
            break;
 
        // for Status
        case FGStatus_Output:
            break;
        case FGStatus_Frequency:
            break;
        case FGStatus_Device:
            break;

        // Special command
        case FGCommand_Reset:
            mbed_reset();
            break;
    }
}

void commandPrint(FGPacket *fgPacket)
{
    pc.printf("command: %d\n", fgPacket->header.command);
    pc.printf("length: %d\n", fgPacket->header.length);
    {
        switch (fgPacket->header.command) {
            case FGCommand_Non:
                pc.printf("FGCommand_Non \n");
                pc.printf("Param:\n");
                pc.printf("  NON\n");
                break;
           case FGCommand_Device:
                pc.printf("FGCommand_Device \n");
                pc.printf("Param:\n");
                pc.printf("  device: %d\n", fgPacket->body.commandDevice.device);
                break;
            case FGCommand_Output:
                pc.printf("FGCommand_Output \n");
                pc.printf("Param:\n");
                pc.printf("  on: %d\n", fgPacket->body.commandOutput.on);
                break;
            case FGCommand_Frequency:
                pc.printf("FGCommand_Frequency \n");
                pc.printf("Param:\n");
                pc.printf(" freq: %d\n", fgPacket->body.commandFrequency.frequency);
                break;

            case FGCommand_WaveformInfo:
                pc.printf("FGCommand_WaveformInfo \n");
                pc.printf("Param:\n");
                pc.printf("  waveSize: %d\n", fgPacket->body.commandWaveformInfo.waveSize);
                pc.printf("  bitPerData: %d\n", fgPacket->body.commandWaveformInfo.bitPerData);
                pc.printf("  blockSize: %d\n", fgPacket->body.commandWaveformInfo.blockSize);
                pc.printf("  blockMaxNum: %d\n", fgPacket->body.commandWaveformInfo.blockMaxNum);
                break;

            case FGCommand_WaveformBlock:
#if 0
                pc.printf("FGCommand_WaveformBlock \n");
                pc.printf("Param:\n");
                pc.printf("  blockNo: %d\n", fgPacket->body.commandWaveformBlock.blockNo);
                pc.printf("  length: %d\n", fgPacket->body.commandWaveformBlock.length);
                pc.printf("  buffer:\n");
                for (int i = 0; i < fgPacket->body.commandWaveformBlock.length; i++) {
                    pc.printf("%02x ", fgPacket->body.commandWaveformBlock.buffer[i]);
                }
                pc.printf("\n");
#endif
                break;

            case FGCommand_WaveformToBuffer:
                pc.printf("FGCommand_WaveformToBuffer \n");
                pc.printf("Param:\n");
                pc.printf("  NON\n");
                break;

            case FGStatus_Output:
                pc.printf("FGStatus_Output \n");
                pc.printf("Param:\n");
                pc.printf("  NON\n");
                break;
            case FGStatus_Frequency:
                pc.printf("FGStatus_Frequency \n");
                pc.printf("Param:\n");
                pc.printf("  NON\n");
                break;
            case FGStatus_Device:
                pc.printf("FGStatus_Device \n");
                pc.printf("Param:\n");
                pc.printf("  NON\n");
                break;
        }
    }
}

//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

int main() {
    pc.baud(115200);
    pc.printf("\n");
    pc.printf("mbed function generator\n");
    pc.printf("--\n");

    {
        gWaveformInfo.waveSize    = WAVE_MASTER_BUFFER_SIZE;
        gWaveformInfo.bitPerData  = 12;
        gWaveformInfo.blockSize   = 16;    // byte
        gWaveformInfo.blockMaxNum = gWaveformInfo.waveSize / gWaveformInfo.blockSize * ((gWaveformInfo.bitPerData + 7) / 8);
    }

    initMasterWaveBuffer();
    masterToReadBufferByFreq(gMasterFrequency);

    i2cSlave.frequency(100000);
    i2cSlave.address(0x62);
    i2cStart.rise(&i2cSlaveAction);

    //upButton.rise(&clickedUpButton);
    //downButton.rise(&clickedDownButton);


    while (1) {
        for (int i = 0; i < gReadBufferLength; i++) {
            //aout.write_u16(gReadBuffer[i]);
            LPC_DAC->DACR = gReadBuffer[i];     // 1data output : MAX 3MHz = 333nS
        }
    }
    
    
    int waitus = 0;
    while (1) {
        for (int i = 0; i < gReadBufferLength; i++) {
            LPC_DAC->DACR = gReadBuffer[i];     // 1data output : MAX 3MHz = 333nS
            wait_us(waitus);
        }
    }

}

//-----------------------------------------------------------------------
//-----------------------------------------------------------------------