同時公開の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
Diff: main.cpp
- 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); + } + } + +} + +//----------------------------------------------------------------------- +//-----------------------------------------------------------------------