For MAX32630FTHR microcontroller: Plays piano notes in Nokia composer format text file placed in the SD card
Dependencies: USBMSD_BD SDFileSystem max32630fthr USBDevice
Diff: main.cpp
- Revision:
- 4:24086b80928e
- Parent:
- 3:fcf745cd4f6d
- Child:
- 5:8ba2f1e291b9
--- a/main.cpp Wed Jul 17 06:11:33 2019 +0000 +++ b/main.cpp Fri Jul 19 04:47:38 2019 +0000 @@ -3,11 +3,7 @@ #include "USBSerial.h" #include "stdio.h" #include "SDFileSystem.h" - -//still needs BITS PER SAMPLE PARSING. -//do this like so: PWM.write(WavValue/2^BPS) - -//MAPPING IS WRONG. P = 440 PLZ. Y = MIDDLE D. +#include "ctype.h" #define BUFFER_SIZE 128 #define HALF_BUFFER 64 @@ -22,16 +18,13 @@ PwmOut PWM(P5_6); AnalogIn POT(AIN_0); volatile int bufferPOS = 0; -volatile unsigned int g=0; Serial daplink(P2_1,P2_0); USBSerial microUSB; -SDFileSystem sd(P0_5, P0_6, P0_4, P0_7, "sd"); float audioDataBuffer[BUFFER_SIZE]; -struct WavFile -{ +struct WavFile { long int size; int channels; int sampleRate; @@ -47,10 +40,10 @@ } int main() -{ +{ WavFile Track; Ticker SampleTime; - + daplink.printf("\f---DAPLINK SERIAL PORT---\r\n\r\nMINI PIANO PLAYER ver 1 \r\n\r\n\r\n"); microUSB.printf("micro USB serial port\r\n"); rLED = LED_ON; @@ -60,7 +53,7 @@ wait_ms(500); bLED = LED_ON; gLED = LED_OFF; - + typedef enum { C2,Cs2,D2,Ds2,E2,F2,Fs2,G2,Gs2,A2,As2,B2, //C2:0 C3,Cs3,D3,Ds3,E3,F3,Fs3,G3,Gs3,A3,As3,B3, //C3:12 @@ -69,43 +62,262 @@ C6,Cs6,D6,Ds6,E6,F6,Fs6,G6,Gs6, //C6:48 rest, END - }pitchname; - + } pitchname; + typedef struct { - float length; + int length; pitchname pitch; } note; + + //input iterator vars + int i; + char c; + //input holder arrays + char buffer[256]; + char inputtype[30]; + typedef enum { + nokiacomposer, + normal + } inputtypes; + inputtypes current_inputtype; + + //parse input type + int g; + tryagain: + printf("Please specify the input type.\r\nAvailable types:\r\nnokiacomposer\r\nnormal\r\n\r\n>"); + for(i=0; i<30; i++) { + c=daplink.getc(); + if(c == '\r') + { + g=i+2; + inputtype[i] = '\0'; + break; + } + daplink.putc(c); + inputtype[i]=c; + } + printf("\r\n"); + for(i=0;i<=g;i++) + { + printf("%i\t",inputtype[i]); + } + printf("\r\nSTRING LITERAL:\r\n"); + char test[] = "nokiacomposer"; + for(i=0;i<=g;i++) + { + printf("%i\t",test[i]); + } + + if(!strcmp(inputtype,"nokiacomposer")) { + printf("\r\nType chosen: nokiacomposer\r\n"); + current_inputtype = nokiacomposer; + } else if(!strcmp(inputtype,"normal")) { + printf("\r\nType chosen: normal\r\n"); + current_inputtype = normal; + } else { + c=NULL; + printf("Invalid input type. Try again."); + goto tryagain; //prints message below input area + } + //open file - +toolarge: + printf("Please copy the text file of the song then right click on the PuTTY screen.\r\n"); + for(i=0; 1; i++) { //do the loop at least once + c=daplink.getc(); + daplink.putc(c); + buffer[i]=c; + if(i>=256) { + printf("Note data is greater than 2kB! Impossible. Try again.\033[A"); + goto toolarge; + } + wait_ms(1); //wait for the next byte to arrive. every byte takes 1.04ms at 9600 baud. + if(!daplink.readable()) + { + printf("That'sallll\r\n"); + break; + } + } + buffer[i] = ' '; //set EOF marker. + buffer[i++] = '\0'; + + //kunwari open na yung file + printf("\r\nFile recieved. Parsing...\r\n"); //parse file into song in heap(remove sharps, put into enums.) + //useful benchmarks to find which characters are valid. + int candidate_number; + char *songpos=buffer+1; //song position + note song[256]; + int pn_det; + + if(current_inputtype == nokiacomposer) { + //for every [note] slot in [song] + for(i=0; i<2048; i++) { + //take the first base 10 integer you see. + //this initializes songpos ALWAYS. lol. + candidate_number = strtol(songpos-1,&songpos,10); + printf("Character:%i\r\n",candidate_number); + //if it's 1,2,4,8,16 or 32, VALID. + if((candidate_number==1)||candidate_number==2||candidate_number==4||candidate_number==8||candidate_number==16||candidate_number==32) { + song[i].length = candidate_number; + printf("Entered candidate [%i] into song[%i].length\r\n",candidate_number,i); + } else { + printf("Found invalid NOTE LENGTH value [%c] at position %li. Skipping until next whitespace...\r\n",*songpos,songpos-buffer); + //skip to after next whitespace + do { + songpos++; + } while(!isspace(*(songpos))); + do { + songpos++; + } while(!isalnum(*(songpos))); + //then do next iteration of LENGTH,PITCH,OCTAVE parse + i--; + continue; + } + //parse next character + printf("Character:%c\r\n",*songpos); + pn_det=0; + //watch out for sharps + if(!(*songpos=='#'||'a'<=*songpos<='z')) { + printf("Found invalid PITCH NAME value [%c] at position %li. Skipping word...\r\n",*songpos,songpos-buffer); + //skip to after next whitespace + do { + songpos++; + } while(!isspace(*(songpos))); + do { + songpos++; + } while(!isalnum(*(songpos))); + //then do next iteration of LENGTH,PITCH,OCTAVE parse + i--; + continue; + } + if(*songpos=='#') { + pn_det+=1; + songpos++; + printf("Sharp found.\r\n"); + } + switch(*songpos) { + case 'c': + pn_det+=0; + break; + case 'd': + pn_det+=2; + break; + case 'e': + pn_det+=4; + break; + case 'f': + pn_det+=5; + break; + case 'g': + pn_det+=7; + break; + case 'a': + pn_det+=9; + break; + case 'b': + pn_det+=11; + break; + } + //check for invalid character at current position + //means that character was valid. move on. + songpos++; + printf("%c\n",*songpos); + if('0'<=*songpos<='9') { + int num = strtol(songpos,&songpos,10); + num+=3;//shift up thrice. board can't handle things this low. + printf("octave parsed: %i \t-> adder:%i\r\n",num,((num-2)*12)); + pn_det=pn_det+((num-2)*12); + } else { + printf("Found invalid OCTAVE value [%c] at position %li. Skipping word...\r\n",*songpos,songpos-buffer); + //skip to after next whitespace + while(!isspace(*(songpos))) { + songpos++; + } + while(!isalnum(*(songpos))) { + songpos++; + } + //then do next iteration of LENGTH,PITCH,OCTAVE parse + i--; + continue; + } + song[i].pitch = (pitchname)pn_det; + printf("Entered pitch [%i] into song[%i].pitch\r\n",song[i].pitch,i); + printf("Final: {%i,%i} at i=%i\r\n",song[i].length,song[i].pitch,i); + printf("-------------------\r\n"); + //make sure you're after the next whitespace + while(!isspace(*(songpos))) { + songpos++; + } + while(isspace(*(songpos))) { + songpos++; + }; + if(*songpos == '\0'){ + printf("NULL found. Escaping...\r\n"); + goto esc; + } + } + } else if(current_inputtype == normal) { + //add normaltype parser here. + } + + //add end term + + //parsing is done +esc: + + printf("at end: i = %i\r\n",i); + i++; + song[i].length = 1; + song[i].pitch = END; + + printf("Parsing done.\r\n"); + + //ENDOFPARSER + + int k; + for(k=0; song[k].pitch != END; k++) { + printf("{%i,%i},",song[k].length,song[k].pitch); + } + printf("{%i,%i},",song[k].length,song[k].pitch); + printf("\r\nPrinting done.\r\n"); + printf("Generating sine...\r\n"); - int i; - for(i=0; i<128;i++) - { + for(i=0; i<128; i++) { audioDataBuffer[i] =((1.0 + sin((double(i)/16.0*6.28318530717959)))/2.0); //formula copied from mbed example } + + /* HERE'S WHERE THE MUSIC STARTS */ + /* LITERALLY. */ + + //FORMAT: { NUM_BEATS, PITCH } + char bpminp[5]; + int PlayingFreq; + + + printf("Please enter desired BPM:\r\n"); + + for(i=0; i<5 && c!='\r'; i++) { + c = daplink.getc(); + daplink.putc(c); + bpminp[i] = c; + } - /* HERE'S WHERE THE MUSIC STARTS */ - /* LITERALLY. */ + printf("BPM Recieved.\r\n"); - //FORMAT: { NUM_BEATS, PITCH } - char c; - char bpminp[5]; - int PlayingFreq; - - restart: + c=NULL; //reset C for next time. + int BPM = strtol(bpminp,NULL,0); + float SPB = 60*4/(float)BPM; - printf("Please enter desired BPM:\r\n"); + printf("BPM: %i",BPM); - for(i=0;i<5 && c!='\r';i++) - { - c = daplink.getc(); - bpminp[i] = c; - } - int BPM = strtol(bpminp,NULL,0); - float SPB = 60/(float)BPM; +restart: + + /* + HARVEST MOON SONG IN NORMAL FORMAT + note song[] = { //batch 1 {4,(pitchname)38},{4,E5},{4,Fs5},{4,D5},{4,Fs5},{4,G5},{4,A5},{4,Fs5},{4,D5}, @@ -124,11 +336,10 @@ //END {1,END} }; - - for(i = 0;1;i++) - { - switch(song[i].pitch) - { + */ + + for(i = 0; 1; i++) { + switch(song[i].pitch) { case rest: wait(song[i].length*SPB); continue; @@ -299,18 +510,25 @@ break; case END: i = 0; + printf("SONG END. PRESS BUTTON TO RESTART."); + while(Button) + { + printf("\033[A\033[A\033[A\033[A"); + } goto restart; } - + Track.sampleRate = PlayingFreq * 16; //TONE FREQ = SAMPLE RATE / SAMPLES PER CYCLE PWM.period_us(1); //1MHz float ticker_period = (float) 1/(Track.sampleRate); printf("\r\nTicker Period: %f\tTicker Freq: %f\r\nTarget Freq: %i \r\n\r\n",ticker_period, 1/ticker_period, PlayingFreq); SampleTime.attach(&placeNewSample,ticker_period); - wait(song[i].length*SPB); + wait( (1/(float)song[i].length) *SPB); SampleTime.detach(); + + printf("\033[A\033[A\033[A\033[A"); } }