同時公開の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...

Revision:
0:cbf811b45305
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jun 16 07:19:51 2015 +0000
@@ -0,0 +1,389 @@
+#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);
+        }
+    }
+
+}
+
+//-----------------------------------------------------------------------
+//-----------------------------------------------------------------------