同時公開のFunctionGenerator-BLEと同時利用によりファンクション・ジェネレータを実現する。
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 / とりあえず写真など
外観
アプリ画面
出力波形
more pictures...
- https://twitter.com/ohneta_j/status/610439975549558784
- https://twitter.com/ohneta_j/status/610480383788871680
- https://twitter.com/ohneta_j/status/610733060594647040
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); } } } //----------------------------------------------------------------------- //-----------------------------------------------------------------------