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

Files at this revision

API Documentation at this revision

Comitter:
ohneta
Date:
Tue Jun 16 07:19:51 2015 +0000
Commit message:
1st release commit

Changed in this revision

FunctionGenCommands.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r cbf811b45305 FunctionGenCommands.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FunctionGenCommands.h	Tue Jun 16 07:19:51 2015 +0000
@@ -0,0 +1,122 @@
+//---------------------------------------------------------
+/**
+ * FunctionGenCommands.h
+ */
+//---------------------------------------------------------
+
+#define FGC_BUFFERTRANSFER_MAX  16
+
+typedef enum {
+    // commands
+    FGCommand_Non = 0x00,
+    FGCommand_Device,
+    FGCommand_Output,
+    FGCommand_Frequency,
+    FGCommand_WaveformInfo,
+    FGCommand_WaveformBlock,
+    FGCommand_WaveformToBuffer,
+
+    // status
+    FGStatus_Device    = 0x80 | FGCommand_Device,
+    FGStatus_Output    = 0x80 | FGCommand_Output,
+    FGStatus_Frequency = 0x80 | FGCommand_Frequency,
+
+    // special
+    FGCommand_Reset = 0xff,  
+    
+} enumFGCommand;
+
+
+// Characteristics
+#define CHARACTERISTICS_UUID_RESET              0xA100
+#define CHARACTERISTICS_UUID_DEVICE             0xA101
+#define CHARACTERISTICS_UUID_OUTPUT             0xA102
+#define CHARACTERISTICS_UUID_FREQUENCY          0xA103
+#define CHARACTERISTICS_UUID_WAVEFORMINFO       0xA110
+#define CHARACTERISTICS_UUID_WAVEFORMBLOCK      0xA111
+#define CHARACTERISTICS_UUID_WAVEFORMTOBUFFER   0xA112
+
+//---------------------------------------------------------
+#pragma pack(1)
+// for BLE waveform transfer format
+
+typedef struct {
+    uint16_t    waveSize;       // Waveform全体のデータ長(byte)  = blockSize * blockMaxNum
+    uint8_t     bitPerData;     // 1データあたりのbit数 (8, 10, 12 or 16bit)
+
+    uint8_t     blockSize;      // 1ブロックあたりのデータ転送サイズ(byte) (通常16bytes)
+    uint8_t     blockMaxNum;    // ブロックの最大数  = (waveSize + 1) / blockSize
+} WaveformInfo, FGCommandWaveformInfo;
+
+typedef struct {
+    uint16_t   blockNo;     // ブロックNo. 0 〜 (WaveformInfo.blockMaxNum - 1)
+    uint8_t    length;      // WaveformBlock.bufferの有効な長さ
+    uint8_t    buffer[FGC_BUFFERTRANSFER_MAX];  // 実際のデータ
+} WaveformBlock, FGCommandWaveformBlock;
+
+//---------------------------------------------------------
+// for I2C packet format
+
+// header
+typedef struct {
+    uint8_t     command;
+    uint8_t     length;
+} FGHeader;
+
+// command bodys
+typedef struct {
+    uint8_t    device;
+} FGCommandDevice;
+
+typedef struct {
+    uint8_t    on;
+} FGCommandOutput;
+
+typedef struct {
+    uint32_t   frequency;
+} FGCommandFrequency;
+
+//#define FGCommandWaveformInfo  WaveformInfo
+//#define FGCommandWaveformBlock WaveformInfoBlock
+
+typedef struct {
+} FGCommandWaveformToBuffer;
+
+typedef struct {
+} FGCommandReset;
+
+// status bodys
+typedef struct {
+    uint8_t    device;
+} FGStatusDevice;
+
+typedef struct {
+    uint8_t    xxx;
+} FGStatusOutput;
+
+typedef struct {
+    uint8_t    xxx;
+} FGStatusFrequency;
+
+
+
+// command Packet format
+typedef struct {
+    FGHeader    header;
+    union {
+        FGCommandDevice             commandDevice;
+        FGCommandOutput             commandOutput;
+        FGCommandFrequency          commandFrequency;
+        FGCommandWaveformInfo       commandWaveformInfo;
+        FGCommandWaveformBlock      commandWaveformBlock;
+        FGCommandWaveformToBuffer   commandWaveformToBuffer;
+
+        FGCommandReset           commandReset;
+
+        FGStatusDevice           statusDevice;
+        FGStatusOutput           statusOutput;
+        FGStatusFrequency        statusFrequency;
+    } body;
+} FGPacket;
+
+#pragma pack()
diff -r 000000000000 -r cbf811b45305 main.cpp
--- /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);
+        }
+    }
+
+}
+
+//-----------------------------------------------------------------------
+//-----------------------------------------------------------------------
diff -r 000000000000 -r cbf811b45305 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Jun 16 07:19:51 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/8ab26030e058
\ No newline at end of file