チーム1823

課題名

Twinkle Star

研究者名

Akiyuki Sato
Ryo Takeyama
Yuka Nagatomo

使用した機器

PSoCMiniProg
ジャンパ線 2本
スピーカー 2つ
PSoC基板
ストレート通信ケーブル

概要

基本としてはきらきら星(TwincleSter)が伴奏つきで流れるというもの。
同時にLCDディスプレイに歌詞が表示され、曲に合わせて流れていく。
さらに、キーボードから読み込んだコマンドによっていろんなことができる(下記に示す)。
愉快な機能としては主旋律を止めて自分で演奏ができるようにした機能。
伴奏は流れているのできらきら星の練習ができる。

~コマンド~
・z : スタート
・n : 一時停止/再生
・r : 初めから
・o : 主旋律カット

~以下は主旋律カット中のみ有効~
・a : ド
・s : レ
・d : ミ
・f : ファ
・g : ソ
・h : ラ
・j : シ
・k : ド

配線

timer7-1_convert_20180612154254.png
timer7-3_convert_20180612154640.png
DSC_1340_convert_20180612163707.jpg


ソースコード


#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
#pragma interrupt_handler myISR

int PW=125;

int SILENT=0, D = 229, L=204, M=182, F=172, S=153, R=136, C=121, DD=115; //音階と周波数の設定

int TC=0, nTC = 0, pTC = 0, STOP = 0, only = 0, p = 0; //Time Countの設定

void myISR(void) {

TC += 1; //TC = TC + 1

PWM16_1_WritePulseWidth(PW);
if(STOP == 0) {
if(TC == 1){
     LCD_1_Init();
     LCD_1_PrCString("Twinkle,twinkle");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("little star!");
     if(only == 0)
     PWM16_1_WritePeriod(D);
     PWM16_2_WritePeriod(D);
     }

else if(TC == 4){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 
 }
 else if(TC == 7){
 if(only == 0)
     PWM16_1_WritePeriod(D);
     PWM16_2_WritePeriod(M);
 }
    
 else if(TC == 10){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 13){
 if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(D);
 }

 else if(TC == 16){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 19){
 if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(M);
 }
        
 else if(TC == 22){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 25){
     LCD_1_Init();
     LCD_1_PrCString("little star!");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("How I wonder");
     if(only == 0)
     PWM16_1_WritePeriod(R);
     PWM16_2_WritePeriod(D);
 }
    
 else if(TC == 28){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(R);
 }

else if(TC == 31){
 if(only == 0)
     PWM16_1_WritePeriod(R);
     PWM16_2_WritePeriod(F);
 }
    
 else if(TC == 34){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(R);
 }
   
 else if(TC == 37){
 if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(D);
 }
    
 else if(TC == 40){
 if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(S);
 }
 
 else if(TC == 43){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(M);
 }
 
 else if(TC == 46){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 49){
       LCD_1_Init();
     LCD_1_PrCString("How I wonder");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("what you are");
     if(only == 0)
     PWM16_1_WritePeriod(F);
     PWM16_2_WritePeriod(C);
 }
    
 else if(TC == 52){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 55){
 if(only == 0)
     PWM16_1_WritePeriod(F);
     PWM16_2_WritePeriod(L);
 }
    
 else if(TC == 58){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 61){
 if(only == 0)
     PWM16_1_WritePeriod(M);
     PWM16_2_WritePeriod(D);
 }
    
 else if(TC == 64){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 67){
 if(only == 0)
     PWM16_1_WritePeriod(M);
     PWM16_2_WritePeriod(M);
 }
            
 else if(TC == 70){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 73){
 LCD_1_Init();
     LCD_1_PrCString("what you are");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("Up above the");
     if(only == 0)
     PWM16_1_WritePeriod(L);
     PWM16_2_WritePeriod(C);
 }
        
 else if(TC == 76){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 79){
 if(only == 0)
     PWM16_1_WritePeriod(L);
     PWM16_2_WritePeriod(L);
 }
        
 else if(TC == 82){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 85){
 if(only == 0)
     PWM16_1_WritePeriod(D);
     PWM16_2_WritePeriod(D);
    }
    
 else if(TC == 88){
 if(only == 0)
     PWM16_1_WritePeriod(D);
     PWM16_2_WritePeriod(S);
 }
 
 else if(TC == 91){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(M);
 }
        
 else if(TC == 94){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
 else if(TC == 97){
 LCD_1_Init();
     LCD_1_PrCString("Up above the");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("world so high");
     if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(D);
     }

else if(TC == 100){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 
 }
 else if(TC == 103){
 if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(M);
 }
    
 else if(TC == 106){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 109){
 if(only == 0)
     PWM16_1_WritePeriod(F);
     PWM16_2_WritePeriod(C);
 }

 else if(TC == 112){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 115){
 if(only == 0)
     PWM16_1_WritePeriod(F);
     PWM16_2_WritePeriod(L);
 }
        
 else if(TC == 118){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 121){
 LCD_1_Init();
     LCD_1_PrCString("world so high");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("Like a diamond");
     if(only == 0)
     PWM16_1_WritePeriod(M);
     PWM16_2_WritePeriod(D);
 }
    
 else if(TC == 124){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 127){
 if(only == 0)
     PWM16_1_WritePeriod(M);
     PWM16_2_WritePeriod(M);
 }
    
 else if(TC == 130){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 133){
 if(only == 0)
     PWM16_1_WritePeriod(L);
     PWM16_2_WritePeriod(C);
 }
 
      
 else if(TC == 136){
 if(only == 0)
     PWM16_1_WritePeriod(L);
     PWM16_2_WritePeriod(S);
 }
 
 else if(TC == 139){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(L);
 }
 
    
 else if(TC == 142){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 145){
 LCD_1_Init();
     LCD_1_PrCString("Like a diamond");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("in the sky.");
     if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(D);
     }

else if(TC == 148){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 
 }
 else if(TC == 151){
 if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(M);
 }
    
 else if(TC == 154){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 157){
 if(only == 0)
     PWM16_1_WritePeriod(F);
     PWM16_2_WritePeriod(C);
 }

 else if(TC == 160){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 163){
 if(only == 0)
     PWM16_1_WritePeriod(F);
     PWM16_2_WritePeriod(L);
 }
        
 else if(TC == 166){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 169){
 LCD_1_Init();
     LCD_1_PrCString("in the sky.");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("Twinkle,twinkle");
     if(only == 0)
     PWM16_1_WritePeriod(M);
     PWM16_2_WritePeriod(D);
 }
    
 else if(TC == 172){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 175){
 if(only == 0)
     PWM16_1_WritePeriod(M);
     PWM16_2_WritePeriod(M);
 }
    
 else if(TC == 178){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 181){
 if(only == 0)
     PWM16_1_WritePeriod(L);
     PWM16_2_WritePeriod(C);
 }
    
 else if(TC == 184){
 if(only == 0)
     PWM16_1_WritePeriod(L);
     PWM16_2_WritePeriod(S);
 }
 
 else if(TC == 187){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(L);
 }
 
 else if(TC == 190){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
 
 else if(TC == 193){
 LCD_1_Init();
     LCD_1_PrCString("Twinkle,twinkle");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("little star!");
     if(only == 0)
     PWM16_1_WritePeriod(D);
     PWM16_2_WritePeriod(D);
     }

else if(TC == 196){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 
 }
 else if(TC == 199){
 if(only == 0)
     PWM16_1_WritePeriod(D);
     PWM16_2_WritePeriod(M);
 }
    
 else if(TC == 202){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 205){
 if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(D);
 }

 else if(TC == 208){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 211){
 if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(M);
 }
        
 else if(TC == 214){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 217){
 LCD_1_Init();
     LCD_1_PrCString("little star!");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("How I wonder");
     if(only == 0)
     PWM16_1_WritePeriod(R);
     PWM16_2_WritePeriod(D);
 }
    
 else if(TC == 220){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(R);
 }

else if(TC == 223){
 if(only == 0)
     PWM16_1_WritePeriod(R);
     PWM16_2_WritePeriod(F);
 }
    
 else if(TC == 226){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(R);
 }
   
 else if(TC == 229){
 if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(D);
 }
    
 else if(TC == 232){
 if(only == 0)
     PWM16_1_WritePeriod(S);
     PWM16_2_WritePeriod(S);
 }
 
 else if(TC == 235){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(M);
 }
 
 else if(TC == 238){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 241){
 LCD_1_Init();
     LCD_1_PrCString("How I wonder");
     LCD_1_Position(1, 0);
     LCD_1_PrCString("what you are");
     if(only == 0)
     PWM16_1_WritePeriod(F);
     PWM16_2_WritePeriod(C);
 }
    
 else if(TC == 244){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 247){
 if(only == 0)
     PWM16_1_WritePeriod(F);
     PWM16_2_WritePeriod(L);
 }
    
 else if(TC == 250){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 253){
 if(only == 0)
     PWM16_1_WritePeriod(M);
     PWM16_2_WritePeriod(D);
 }
    
 else if(TC == 256){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }
   
 else if(TC == 259){
 if(only == 0)
     PWM16_1_WritePeriod(M);
     PWM16_2_WritePeriod(M);
 }
            
 else if(TC == 262){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 265){
       LCD_1_Init();
     LCD_1_Position(1, 0);
     LCD_1_PrCString("what you are");
     if(only == 0)
     PWM16_1_WritePeriod(L);
     PWM16_2_WritePeriod(C);
 }
        
 else if(TC == 268){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 271){
 if(only == 0)
     PWM16_1_WritePeriod(L);
     PWM16_2_WritePeriod(L);
 }
        
 else if(TC == 274){
 if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(S);
 }

else if(TC == 277){
 if(only == 0)
     PWM16_1_WritePeriod(D);
     PWM16_2_WritePeriod(D);
    }
        
 else if(TC == 280){
       LCD_1_Init();
     LCD_1_PrCString("     ~Fin~");
     if(only == 0)
     PWM16_1_WritePeriod(SILENT);
     PWM16_2_WritePeriod(SILENT);
   }
 }
}
void main(void)
{
  // M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts
   // Insert your main routine code here.
   char* strPtr;
   
   //キーボード入力とモジュールの開始
     UART_CmdReset();
     UART_IntCntl(UART_ENABLE_RX_INT);
   Counter8_WritePeriod(155);
   Counter8_WriteCompareValue(77);
   Counter8_Start();
     UART_Start(UART_PARITY_NONE);
     M8C_EnableGInt;
   UART_CPutString("\r\nキラキラ星\n");
   UART_CPutString("\r\n液晶に歌詞が表示されます\n");
   UART_CPutString("\r\nz : スタート\n");
   UART_CPutString("\r\nn : 一時停止 再開\n");
   UART_CPutString("\r\nr : 始めから\n");
   UART_CPutString("\r\no : 主旋律カット\n");
   UART_CPutString("\r\n主旋律カット中は演奏できます\n\r");
   LCD_1_Start(); 
   PWM16_2_Start();
   PWM16_1_Start();
   
   //キーボード入力の対応
   while(1) {
   
   //主旋律カット中の演奏を0,5拍ごとに切る
   if((TC >= pTC + 3) && p == 1) {
       PWM16_1_WritePeriod(SILENT);
       p = 0;
   }
   
      if(UART_bCmdCheck()){
         if(strPtr = UART_szGetParam()){
           UART_PutString(strPtr);
           
           //スタート
           if(*strPtr=='z') {
               Timer16_1_EnableInt();
               Timer16_1_Start();
           }
       
           //一時停止 再開
           if(*strPtr=='n') {
             if(STOP == 0) {
                PWM16_1_WritePeriod(SILENT);
                PWM16_2_WritePeriod(SILENT);
                nTC = TC;
                TC = 0;
                STOP = 1;
                } else {
                TC = nTC;
                STOP = 0;
                }
           }
           
           //始めから
           if(*strPtr=='r') {
             TC = 0;
             PWM16_1_WritePeriod(SILENT);
             PWM16_2_WritePeriod(SILENT);
             Timer16_1_Stop();
             STOP = 0;
             Timer16_1_Start();
           }
           
           //主旋律カット
           if(*strPtr=='o') {
             if(only == 0) {
                 UART_CPutString("\r\n”主旋律カット中”\n");
               UART_CPutString("\r\na:ド s:レ d:ミ f:ファ g:ソ  h:ラ  j:シ  k:ド\n\r");
                only = 1;
                PWM16_1_WritePeriod(SILENT);
             } else {
                only = 0;
                UART_CPutString("\r\n”主旋律カット終了”\n");
             }
           }
           
           //主旋律カット中の演奏
           if(only == 1) {
           if(*strPtr=='a') {
            if(p == 0) {
               PWM16_1_WritePeriod(D);
               pTC = TC;
               p = 1;
            } 
           } else if(*strPtr=='s') {
            if(p == 0) {
               PWM16_1_WritePeriod(L);
               pTC = TC;
               p = 1;
            } 
           } else if(*strPtr=='d') {
            if(p == 0) {
               PWM16_1_WritePeriod(M);
               pTC = TC;
               p = 1;
            } 
           } else if(*strPtr=='f') {
            if(p == 0) {
               PWM16_1_WritePeriod(F);
               pTC = TC;
               p = 1;
            } 
           } else if(*strPtr=='g') {
            if(p == 0) {
               PWM16_1_WritePeriod(S);
               pTC = TC;
               p = 1;
            }
           } else if(*strPtr=='h') {
            if(p == 0) {
               PWM16_1_WritePeriod(R);
               pTC = TC;
               p = 1;
            } 
           } else if(*strPtr=='j') {
            if(p == 0) {
               PWM16_1_WritePeriod(C);
               pTC = TC;
               p = 1;
            }
           } else if(*strPtr=='k') {
            if(p == 0) {
               PWM16_1_WritePeriod(DD);
               pTC = TC;
               p = 1;
            } 
           }
           }
           }
       UART_CmdReset();
       }
   }
}

考察

この装置はラボtimer_pwm2、チーム1751(コマンドでの一時停止/再生と強制終了)、チーム1762(演奏とLCDディスプレイ表示)、チーム1731(複数スピーカーによる演奏)を参考に作成した。
timer_pwm2と同様にTC(タイムカウント)を基準に音を発生させているが細部が異なる。

概要にも書いた通り、いろいろな機能を実装することができた。
速度変更機能を実装しようとしたが、掛け算を利用した数式が思いどうりに動かず断念した。
ほかの曲を追加し、違う曲を選ぶコマンド、次の曲・前の曲などのコマンドを作ればさらによいものになるだろう。
音符を一つ一つ打つだけでなく音楽のリズムをTCを一つずつずらしながら変えていかなくてはならないのが大変なので、何かいいコードをかけたらもっと曲を増やすのも楽になり、優れたプログラムになると考えられる。
別のファイルとして用意した楽譜を読み取って演奏する方式も考えられる。

主旋律カット中に演奏できる音は鳴らした音を0.5拍(TC+3)で消音しているため4分音符のみである。
曲中には2分音符(TC+12)を使用する部分があるため正しく演奏することはできない。
別途2分音符の演奏ができるボタンを用意することで解決はするが、現実と同じ仕様である押した長さに応じて音の長さが変わる方式にしたほうが良いだろうが、
現在のやり方ではコマンドの入力以外の情報を受け取っていないため難しいだろう。

今回演奏するきらきら星は伴奏含め16分音符を使用する部分がない。
もし16分音符を使用する曲を演奏しようとした場合、4分音符一拍をTC+6としているため16分音符は0.25拍でありTC+1.5であるため鳴らすことができない。
現在の方式のまま16分音符を演奏するには、速度を下げる必要が出てくる。

  • 最終更新:2018-06-12 16:38:47

このWIKIを編集するにはパスワード入力が必要です

認証パスワード