Stefan Poels
/
MLX8030x_B6PV_Demo
MLX8030x_B6PV_Demo
Revision 0:f0d7e4b016ce, committed 2014-09-05
- Comitter:
- StefanP
- Date:
- Fri Sep 05 13:28:28 2014 +0000
- Commit message:
- MLX8030x_B6PV_Demo
Changed in this revision
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 |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Sep 05 13:28:28 2014 +0000 @@ -0,0 +1,557 @@ +#include "mbed.h" +#include "LPC17xx.h" + +#define GUI 1 +#define TeraTerm 0 + +LocalFileSystem local("local"); + +Serial pc(USBTX, USBRX); + +DigitalOut LedSpi(LED1); // LED active during SPI communication +PwmOut LedDiagn(LED2); // LED active with duty cycle of B6PV "DIAG"-pin +DigitalOut LedUSB(LED3); // LED active if USB connection is established with GUI +DigitalOut LedApplication(LED4); // LED active when application is running + +PwmOut pwmon(p26); // B6PV "PWMON"-pin +DigitalIn spibusy(p9); // B6PV "SPI_BUSY"-pin +SPI spi(p5, p6, p7); // B6PV "MOSI", "MISO", "CLK"-pins +DigitalOut cs(p8); // B6PV "CS"-pin + +DigitalOut OCsimulation(p24); + +int iPWMPeriod = 1000; // Set initial PWM period to 1000us or 1kHz +float fPWMDutyCycle = 0.0; // Set initial duty cycle to 0.0 or 0% -> OFF + +volatile uint32_t u32DiagnDC = 0; // Duty cycle from the diagnostics input +const uint16_t DUTY_CYCLE_ACCURACY = 1000; // Used to enhance the duty cycle calculation (HighTime * 1000)/Period +volatile uint32_t u32DiagnPeriod = 0; // Period from the diagnostics input +const uint32_t u32DiagnMaxPeriod = 9600000;// Minimum 10Hz diagnostics frequeny (96MHz/10Hz=9.6e6) +volatile uint32_t u32DiagnCapA = 0; // Timer capture for a falling edge of diagnostics input +volatile uint32_t u32DiagnCapB = 0; // Timer capture for a rising edge of diagnostics input +volatile bool bTimer2MR0 = false; // Timer2 reached match register MR0 (used to detect 0% and 100% duty cycle) + +volatile uint32_t u32SpeedCapA = 0; // Timer capture for a 1st edge of speed feedback +volatile uint32_t u32SpeedCapB = 0; // Timer capture for a 2nd edge of speed feedback +volatile uint32_t u32Speed = 0; // Minimum speed +const uint32_t u32SpeedMaxPeriod= 16000000;// Minum 1eHz = 6Hz commutation speed (96MHz/6Hz=16e6) +volatile bool bTimer2MR1 = false; // Timer2 reached match register MR1 (used to detect 0eHz speed = motor still) + +bool bUsbConnected = false; // Boolean to indicate USB connection with GUI + +void SpiInit(void); // SPI initialization +void Timer2Init(void); // Timer 2 initialization +void SerialUSBInit(void); // Serial USB intialization +void TIMER2_IRQHandler(void); // Timer 2 interrupt handler for determining diagnostics duty cycle +uint32_t TransceiveSpiFrame(uint32_t); // Transceive one SPI frame: Transmit MOSI - Receive MISO + +int main() { + + SpiInit(); + Timer2Init(); + SerialUSBInit(); + + int iCnt = 0; + uint32_t u32SPIframe = 0; + uint32_t u32result = 0; + + pwmon.period_us(iPWMPeriod); + pwmon.write(fPWMDutyCycle); + + while(1) + { + LedApplication = 1; + LedDiagn = float(u32DiagnDC)/DUTY_CYCLE_ACCURACY; + + #if GUI + char strCommand[8]; + if (pc.readable()) + { + int err = pc.scanf("%s",&strCommand); + if ((strCommand[0] == 'I') && (strCommand[1] == 'D')) + { + if (pc.writeable()) + pc.printf("MBED\n"); + + int err = pc.scanf("%s",&strCommand); + if ((strCommand[0] == 'O') && (strCommand[1] == 'K')) + { + bUsbConnected = true; + LedUSB = 1; + } + } + else if (strCommand[0] == 'X') + { + bUsbConnected = false; + LedUSB = 0; + } + } + #endif //GUI + + #ifdef TeraTerm + char c = pc.getc(); + switch (c) + { + case '\r': // If 'enter' is pressed, send the SPI MOSI-frame + if (!spibusy) + { + // Show SPI communication active via LED + LedSpi = 1; + wait(0.1); + u32result = TransceiveSpiFrame(u32SPIframe); + LedSpi = 0; + + pc.printf("\nThe SPI MOSI-frame send = 0x%.8X \n", u32SPIframe); + pc.printf("The SPI MISO-frame received = 0x%.8X\n", u32result); + + iCnt = 0; + //u32SPIframe = 0; + } + else + { + pc.printf("\nSPI busy \nPress enter to try again \n"); + } + + pc.printf("The diagnostics frequency is %uHz \n", SystemCoreClock/u32DiagnPeriod); + pc.printf("The diagnostics duty cycle is %.1f%%\n\n", float(u32DiagnDC)/DUTY_CYCLE_ACCURACY*100); + //pc.printf("The speed is %u eHz \n", u32Speed); + + break; + + case '1': // Set '1' in SPI MOSI-frame to be send + if (iCnt == 0) + u32SPIframe = (1<<31); + else + u32SPIframe |= (1<<(31-iCnt)); // shift bits: first entered is MSB + iCnt++; + pc.printf("%c",c); // print entered character + if (iCnt > 31) // 32-bits can be entered (circular) + iCnt = 0; + else if (((iCnt) % 4) == 0) // print space every 4-bits + pc.printf(" "); + break; + + case '0': // Set '0' in SPI MOSI-frame to be send + if (iCnt == 0) + u32SPIframe = 0; + else + u32SPIframe &=~ (1<<(31-iCnt)); // shift bits: first entered is MSB + iCnt++; + pc.printf("%c",c); // print entered character + if (iCnt > 31) // 32-bits can be entered (circular) + iCnt = 0; + else if (((iCnt) % 4) == 0) // print space every 4-bits + pc.printf(" "); + break; + + case 'h': // PWM higher frequency + if ((iPWMPeriod - 10) > 100) // max 10kHz or 100us + { iPWMPeriod -= 10;} + else + { iPWMPeriod = 100;} + pwmon.period_us(iPWMPeriod); + pwmon.write(fPWMDutyCycle); // bug in mbed that duty cycle is not maintained on update of period + break; + + case 'l': // PWM lower frequency + if ((iPWMPeriod + 10) < 10000) // min 100Hz or 10000us + { iPWMPeriod += 10;} + else + { iPWMPeriod = 10000;} + pwmon.period_us(iPWMPeriod); + pwmon.write(fPWMDutyCycle); // bug in mbed that duty cycle is not maintained on update of period + break; + + case 'b': // PWM bigger duty cycle + if ((fPWMDutyCycle + 0.001) < 1) // max 100% duty cycle + { fPWMDutyCycle += 0.001;} + else + { fPWMDutyCycle = 1;} + pwmon.write(fPWMDutyCycle); + break; + + case 's': // PWM smaller duty cycle + if ((fPWMDutyCycle - 0.001) > 0) // min 0% duty cycle + { fPWMDutyCycle -= 0.001;} + else + { fPWMDutyCycle = 0;} + pwmon.write(fPWMDutyCycle); + break; + + case 'r': // read + //pc.printf("Read FPGA register 1"); + //u32SPIframe = 0xCF020000; + //u32SPIframe |= (1<<16); + //u32SPIframe |= 0x00000000; + u32result = TransceiveSpiFrame(0xCF090000);//(0xCC290000); + pc.printf("Read FPGA register 4 returns 0x%.8X \n",u32result); + + break; + + case 'w': //write + //pc.printf("Write 0xA16C to FPGA register 1"); + //u32SPIframe = 0xCF020000; + //u32SPIframe |= (0<<16); + //u32SPIframe |= 0x0000A16C; + u32result = TransceiveSpiFrame(0xCF083182);//(0xCC28FFFF); + pc.printf("Write FPGA register 4 returns 0x%.8X \n",u32result); + break; + + case 'i': // read ID from B6PV + u32result = TransceiveSpiFrame(0xCC810000); + if (u32result == 0x00000000) + pc.printf("B6PV - DOE1 \n"); + else if (u32result == 0x00000001) + pc.printf("B6PV - DOE2 \n"); + else if (u32result == 0x00000002) + pc.printf("B6PV - DOE3 \n"); + else if (u32result == 0x00000003) + pc.printf("B6PV - DOE4 \n"); + else + pc.printf("B6PV - Read ID error \n B6PV returns 0x%.8X \n",u32result); + break; + + case 't': // trim B6PV and configure FPGA + u32result = TransceiveSpiFrame(0xCC0A0001); // DOE1_IC5_TRIM_VDDA + u32result = TransceiveSpiFrame(0xCC0C0001); // DOE1_IC5_TRIM_VDDD + u32result = TransceiveSpiFrame(0xCC0E0001); // DOE1_IC5_TRIM_VBG + u32result = TransceiveSpiFrame(0xCC100004); // DOE1_IC5_TRIM_IBIAS + u32result = TransceiveSpiFrame(0xCC3A0016); // DOE1_IC5_TRIM_RCO + + u32result = TransceiveSpiFrame(0xCF000200); // Set PWM mode + u32result = TransceiveSpiFrame(0xCF02FFFF); // Set current limit to max + u32result = TransceiveSpiFrame(0xCF04FFFF); // Set current limit to max + u32result = TransceiveSpiFrame(0xCF06FFFF); // Set + u32result = TransceiveSpiFrame(0xCF083182); // Set ALIGN1-2_TIME, STEP1_TIME + u32result = TransceiveSpiFrame(0xCF0A0CE9); // Set STEP2-4_TIME + u32result = TransceiveSpiFrame(0xCF0C0010); // Set wait time to ??? + u32result = TransceiveSpiFrame(0xCF0E0000); // Set timer6-7 + u32result = TransceiveSpiFrame(0xCF100000); // Set CW + u32result = TransceiveSpiFrame(0xCF120003); // Set rotor trials to 3 + + u32result = TransceiveSpiFrame(0xCF3A0001); // Set EE_READY + + pc.printf("\nTrimming of B6PV and start-up configuration in FPGA done \n"); + break; + + case 'g': // trim B6PV and configure FPGA + if (fPWMDutyCycle == 0) + { + fPWMDutyCycle = 0.5; + pwmon.write(fPWMDutyCycle); + } + else + { + fPWMDutyCycle = 0.0; + pwmon.write(fPWMDutyCycle); + } + pc.printf("\nSet PWM/ON to %1.1f%% duty cycle on PWM-ON pin\n",fPWMDutyCycle*100); + + break; + + case 'n': //write to FPGA to turn LED on + u32SPIframe = 0xCF3E8000; + u32result = TransceiveSpiFrame(u32SPIframe); + pc.printf("\nLED on \n"); + break; + + case 'f': //write to FPGA to turn LED off + u32SPIframe = 0xCF3E0000;//0xCF3E0000; + u32result = TransceiveSpiFrame(u32SPIframe); + pc.printf("\nLED off \n"); + break; + + case '2': //write to FPGA to turn LED off + u32SPIframe = 0xCF360081; + u32result = TransceiveSpiFrame(u32SPIframe); + pc.printf("\nInduce soft error 0 by sending MOSI frame = 0x%.8X \n", u32SPIframe); + break; + case '3': //write to FPGA to turn LED off + u32SPIframe = 0xCF360082; + u32result = TransceiveSpiFrame(u32SPIframe); + pc.printf("\nInduce soft error 1 by sending MOSI frame = 0x%.8X \n", u32SPIframe); + break; + case '4': //write to FPGA to turn LED off + u32SPIframe = 0xCF360084; + u32result = TransceiveSpiFrame(u32SPIframe); + pc.printf("\nInduce soft error 2 by sending MOSI frame = 0x%.8X \n", u32SPIframe); + break; + case '5': //write to FPGA to turn LED off + u32SPIframe = 0xCF360088; + u32result = TransceiveSpiFrame(u32SPIframe); + pc.printf("\nInduce soft error 3 by sending MOSI frame = 0x%.8X \n", u32SPIframe); + break; + case '6': //write to FPGA to turn LED off + u32SPIframe = 0xCF360090; + u32result = TransceiveSpiFrame(u32SPIframe); + pc.printf("\nInduce soft error 4 by sending MOSI frame = 0x%.8X \n", u32SPIframe); + break; + case '7': //write to FPGA to turn LED off + u32SPIframe = 0xCF3600A0; + u32result = TransceiveSpiFrame(u32SPIframe); + pc.printf("\nInduce soft error 5 by sending MOSI frame = 0x%.8X \n", u32SPIframe); + break; + case '8': //write to FPGA to turn LED off + u32SPIframe = 0xCF3600C0; + u32result = TransceiveSpiFrame(u32SPIframe); + pc.printf("\nInduce soft error 6 by sending MOSI frame = 0x%.8X \n", u32SPIframe); + break; + case '9': //write to FPGA to turn LED off + u32SPIframe = 0xCF3600FF; + u32result = TransceiveSpiFrame(u32SPIframe); + wait(0.0011); + u32SPIframe = 0xCF360080; + u32result = TransceiveSpiFrame(u32SPIframe); + pc.printf("\nInduce all soft errors by sending MOSI frame = 0x%.8X followed by removing all soft errors \n", u32SPIframe); + break; + + case 'o': // give a pulse on FPGA OC-pin to simulate over current error + OCsimulation = 1; + wait(0.0001); + OCsimulation = 0; + break; + + case 'a': //try to write 0xFFFF to all FPGA register addresses [31:0] + int iSpiErrCnt = 0; + for (uint32_t i3=0; i3<0x0000FFFF; i3+=0x00000155) + { + uint32_t u32MosiWriteFrame = 0xCF000000; + uint32_t u32MosiReadFrame = 0xCF010000; + pc.printf("Using data 0x%.8X to test read instruction \n", i3); + for (int i2=0; i2<32; i2++) + { + //pc.printf("Testing address %i\n", i2); + for (int i1=0; i1<0x0000FFFF; i1++) + { + uint32_t u32MisoWriteFrame = TransceiveSpiFrame(u32MosiWriteFrame+i1); + //pc.printf("The SPI MOSI-frame to write = 0x%.8X \nThe SPI MISO-frame received = 0x%.8X \n", u32SPIframe,u32result); + wait(0.00001); + uint32_t u32MisoReadFrame = TransceiveSpiFrame(u32MosiReadFrame+i3); + //pc.printf("The SPI MOSI-frame to read = 0x%.8X \nThe SPI MISO-frame received = 0x%.8X \n", u32SPIframe,u32result); + if ((u32MisoReadFrame & 0x0000FFFF) != i1) + { + iSpiErrCnt++; + pc.printf("The SPI MOSI-frame to write = 0x%.8X \nThe SPI MISO-frame received to write = 0x%.8X \n", u32MosiWriteFrame+i1,u32MisoWriteFrame); + pc.printf("The SPI MOSI-frame to read = 0x%.8X \nThe SPI MISO-frame received to read = 0x%.8X \n", u32MosiReadFrame+i3,u32MisoReadFrame); + } + } + u32MosiWriteFrame += 0x00020000; + u32MosiReadFrame += 0x00020000; + } + pc.printf("The number of SPI errors = %i \n", iSpiErrCnt); + } + break; + + case 'p': //PWM decoder test [31:0] + u32result = TransceiveSpiFrame(0xCF000200); + FILE *Datalogging = fopen("/local/PWMDecoder.csv", "w"); + for (int i1=10000; i1>80; i1=i1*0.90) + { + pwmon.period_us(i1); + for (float f1=0.2; f1>0; f1-=0.001) + { + pwmon.write(f1); + //float fWaitTime = (float)(i1*5)/(1000000); + wait(0.1); + fprintf(Datalogging, "%i-%.4f+%u*%.2f\n", i1,f1,u32DiagnPeriod,float(u32DiagnDC)/DUTY_CYCLE_ACCURACY*100); + } + for (float f1=0.0; f1<=1.001; f1+=0.001) + { + pwmon.write(f1); + //float fWaitTime = (float)(i1*5)/(1000000); + wait(0.1); + fprintf(Datalogging, "%i-%.4f+%u*%.2f\n", i1,f1,u32DiagnPeriod,float(u32DiagnDC)/DUTY_CYCLE_ACCURACY*100); + } + } + fclose(Datalogging); + break; + + + } + #endif //TeraTerm + } +} + + +/* ************************************************************************************** + * Setup the spi for 16 bit data, high steady state clock, + * base value of the clock is zero CPOL = 0 + * data captured on the rising edge and data propagated on a falling edge = CPHA = 0 + * SPImode = [CPOL CPHA] = [01] = 1 + * with a 1MHz clock rate + ****************************************************************************************/ + +void SpiInit() { + cs = 1; + spi.format(16,0); + spi.frequency(1000000); +} + + +uint32_t TransceiveSpiFrame(uint32_t u32MosiMessage){ + +// LPC_PINCON->PINSEL0 &=~ 0x0000C000; // Set p7(=P0.7) to GPIO mode +// LPC_GPIO0->FIODIR |= (1<<7); // Set p7 as output +// LPC_GPIO0->FIOSET = (1<<7); // Set p7 high +// LPC_GPIO0->FIOCLR = (1<<7); // Set p7 low +// LPC_PINCON->PINSEL0 |= 0x00008000; // Set p7(=P0.7) to SPI-SCK mode + + // Select the device by seting chip select low + cs = 0; + + // Send first 16 bit of 32-bit frame + uint32_t u32MisoMessage = (spi.write((uint16_t)(u32MosiMessage>>16))<<16); + + // Send second 16 bit of 32-bit frame + u32MisoMessage |= spi.write((uint16_t)(u32MosiMessage)); + + // Deselect the device + wait(0.0000000000000001); + cs = 1; + + return u32MisoMessage; +} + +/* ************************************************************************************** + * Setup the spi for 16 bit data, high steady state clock, + * base value of the clock is zero CPOL = 0 + * data captured on the falling edge and data propagated on a rising edge = CPHA = 1 + * SPImode = [CPOL CPHA] = [01] = 1 + * with a 1MHz clock rate + ****************************************************************************************/ + +void SerialUSBInit() { + pc.format(8, Serial::None, 1); + pc.baud(9600); +} + + +/* ************************************************************************************** + * Setup TIMER2 to capture edges on two seperate channels + * - Channel 0 : B6PV "DIAG"-pin + * Capture alternating rising/falling edge to determine duty cycle + * - Channel 1 : B6PV "SPEED"-pin + * Capture rising/falling edges to determine average high-low time + ****************************************************************************************/ +void Timer2Init(){ + + LPC_PINCON->PINSEL0 |= 0x00000300; // Set p30(=P0.4) to CAP2.0 = B6PV "DIAG"-pin + LPC_PINCON->PINMODE0 |= 0x00000200; // set p30(=P0.4) to have neither pull-up nor pull-down resistors + + LPC_PINCON->PINSEL0 |= 0x00000C00; // set p29(=P0.5) to CAP2.1 = B6PV "SPEED"-pin + LPC_PINCON->PINMODE0 |= 0x00000800; // set p29(=P0.5) to have neither pull-up nor pull-down resistors + + NVIC_SetVector(TIMER2_IRQn, uint32_t(TIMER2_IRQHandler)); + NVIC_EnableIRQ(TIMER2_IRQn); + //NVIC_DisableIRQ(TIMER2_IRQn); + + LPC_SC->PCONP |= (1 << 22); // Timer2 power on + LPC_SC->PCLKSEL1 |= (1 << 12); // Divide CCLK by 1 for Timer2 + + LPC_TIM2->TC = 0; // Clear timer counter + LPC_TIM2->PC = 0; // Clear prescale counter + LPC_TIM2->PR = 0; // Clear prescale register + LPC_TIM2->CTCR = 0x00; // Set timer mode + LPC_TIM2->TCR |= (1 << 1); // Reset timer + LPC_TIM2->TCR &=~(1 << 1); // Release reset + LPC_TIM2->IR = 0xFFFFFFFF; // Clear interrupt register + + LPC_TIM2->CCR |=(1<<0); // Enable cap2.0 on rising edge + LPC_TIM2->CCR |=(1<<2); // Enable interrupt on cap2.0 event + LPC_TIM2->MR0 = u32DiagnMaxPeriod; // Match register 0 for 0%-100% detection + LPC_TIM2->MCR |=(1<<0); // Enable interrupt when TIM2 reaches MR0 + + LPC_TIM2->CCR |=((1<<3)|(1<<4)); // Enable cap2.1 on rising and falling edge + LPC_TIM2->CCR |=(1<<5); // Enable interrupt on cap2.1 event + LPC_TIM2->MR0 = u32SpeedMaxPeriod; // Match register 1 for motor speed 0 detection + LPC_TIM2->MCR |=(1<<3); // Enable interrupt when TIM2 reaches MR1 + + LPC_TIM2->TCR |= (1 << 0); // start Timer2 +} + + +/* ********************************************************************************** + * + ************************************************************************************/ +void TIMER2_IRQHandler(void) +{ + uint32_t pending = LPC_TIM2->IR; + + /********************************************************** + * If timer2 capture channel 0 interrupt + * Used for edge detection on DIAG-pin (duty cycle) + **********************************************************/ + if(pending & (1<<4)) // if timer2 interrupt on capture channel 0 = DIAGNOSTICS + { + if(LPC_TIM2->CCR & (1<<0)) // if cap2.0 rising edge + { + LPC_TIM2->CCR &=~(1<<0); // disable cap2.0 rising edge + + u32DiagnCapA = LPC_TIM2->CR0; + + LPC_TIM2->CCR |= (1<<1); // enable cap2.0 falling edge + } + else if (LPC_TIM2->CCR & (1<<1)) // if cap2.0 falling edge + { + LPC_TIM2->CCR &=~(1<<1); // disable cap2.0 falling edge + + uint32_t u32DiagnCapBtemp = LPC_TIM2->CR0; + uint32_t diagnHighT = u32DiagnCapBtemp - u32DiagnCapA; + + if ((u32DiagnCapBtemp-u32DiagnCapB)>(u32DiagnPeriod+(u32DiagnPeriod>>1))) + u32DiagnPeriod = ((u32DiagnCapBtemp-u32DiagnCapB)>>1); + else + u32DiagnPeriod = u32DiagnCapBtemp-u32DiagnCapB; + + if (diagnHighT<u32DiagnPeriod) + u32DiagnDC = (diagnHighT*DUTY_CYCLE_ACCURACY)/u32DiagnPeriod; + + u32DiagnCapB = u32DiagnCapBtemp; + + LPC_TIM2->CCR |= (1<<0); // enable cap2.0 rising edge + } + + LPC_TIM2->IR |= (1<<4); // clear Timer2 interrupt flag for capture channel 0 event + LPC_TIM2->MR0 = LPC_TIM2->TC + (u32DiagnMaxPeriod<<1); + } + else if(pending & (1<<0)) + { + if(LPC_TIM2->CCR & (1<<1)) + u32DiagnDC = 1*DUTY_CYCLE_ACCURACY; + else + u32DiagnDC = 0; + + u32DiagnPeriod = 0xFFFFFFFF; + LPC_TIM2->IR |= (1<<0); // clear Timer2 interrupt flag for match register 0 event + LPC_TIM2->MR0 = LPC_TIM2->TC + (u32DiagnMaxPeriod<<1); + } + + /********************************************************** + * If timer2 capture channel 1 interrupt + * Used for edge detection on SPEED-pin (high / low time) + **********************************************************/ + if(pending & (1<<5)) + { + u32SpeedCapA = u32SpeedCapB; + u32SpeedCapB = LPC_TIM2->CR1; + + // Calculate time between 2 edges = commutation time [us] + uint32_t tempCommTime = ((u32SpeedCapB-u32SpeedCapA)/96); + + // Calculate averaged speed via 1/(6 x commutation time) [eHz] + u32Speed = ((u32Speed + (1000000000/(tempCommTime*6)))>>1); + + // Clear timer2 chanel 1 interrupt flag + LPC_TIM2->IR |= (1<<5); + + // + LPC_TIM2->MR1 = LPC_TIM2->TC + (u32SpeedMaxPeriod<<1); + } + else if(pending & (1<<1)) + { + u32Speed = 0; + LPC_TIM2->IR |= (1<<1); // clear Timer2 interrupt flag for match register 0 event + LPC_TIM2->MR1 = LPC_TIM2->TC + (u32SpeedMaxPeriod<<1); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Sep 05 13:28:28 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/024bf7f99721 \ No newline at end of file