File content as of revision 0:a53877d0ea3d:
/***********************************************************************/
/* */
/* Sound.cpp */
/* */
/* misoOutput - digtalOutput de sound syuturyoku suru library */
/***********************************************************************/
#define _SOUND_C
#include "types.h"
#include "mbed.h"
#include "math.h"
#include "SoundSPI.h"
LocalFileSystem local("local");
/*******************************************************************
* syokika
*******************************************************************/
Sound::Sound(PinName pwm, PinName kijun) : _pwm(pwm, NC, NC), _kijun(kijun){
/***********************
* kido ji no yobidasi
***********************/
sound_timer.attach_us(this, &Sound::pulseCheck, Z_pulseCheckSyuuki); // oto no hakei syuturyoku check time
hatuon_jikan.start(); // 1tu no oto no hatuon jikan kakunin
_pwm.format(Z_pwmBunkaino, 0);
// _pwm.frequency((1000000 /Z_pwmSyuuki) * 16);
_pwm.frequency(1500000);
_pwm.write(0x0000);
_kijun = 0;
keikajikan = 0; // 1tu no oto no keikajikan
F_pwmSet = 0; // 0:zenhan hansyuuki 1:kohan hansyuuki wo request
C_syuukiKeika = 0;
f_muonSet = 0; // muon ji no sound_out() syori wo kurikaesu no wo fusegu
}
/*****************************************
* analog output
* siji : syuturyoku siji (0.0 - 1.0) absolute
* fugo : syuturyoku fugo 0:+ 1:-
*****************************************/
void Sound::sound_out(float siji, int8_t fugo){
// siji no atai wo fugo ga minus no toki hanten
if(fugo == 1){siji = 1.0 - siji;}
_kijun = fugo;
// pwm sijichi no henkan siji:float(0.0 - 1.0) kara sijibit:uint8_t(0 - 16), siji_miso:uint16_t(0x0000, 0x0001, 0x0003, ... ,0xFFFE, 0xFFFF)
uint8_t sijibit = uint8_t(siji * Z_pwmBunkaino); // 0.0 - 1.0 wo 0 - 16(Z_pwmBunkaino) ni henkan
uint16_t siji_miso = 0;
for(uint8_t i = 0; i < sijibit; i++){
siji_miso = siji_miso << 1;
siji_miso |= 0x0001;
}
D_SPIpwm = siji_miso;
// _pwm.write(siji_miso); // 2tuizyo sound out settei site ,interrupt no nakade renzoku de pwm set wo suruto bousou suru.
}
/*****************************************
* sound hakei pwm output
* time interrupt
*****************************************/
void Sound::pulseCheck(void) {
// uint32_t static C_syuukiKeika = 0;
// uint8_t static f_muonSet = 0; // muon ji no sound_out() syori wo kurikaesu no wo fusegu
// uint8_t static F_pwmSet = 0; // 0:zenhan hansyuuki 1:kohan hansyuuki wo request
float D_soundOut; // syuturyoku suru sinpuku chi (0.0 - 1.0)
if (O_sound.syuuki != 0) {
f_muonSet = 1;
// sound ari
if (C_syuukiKeika < (O_sound.syuuki / 2.0)) {
// zenhan han syuuki
if (F_pwmSet == 0) {
F_pwmSet = 1;
D_soundOut = (float)pow(((double)O_sound.envelope / O_sound.shokichienvelope), 2.0);
sound_out(D_soundOut, 0);
}
C_syuukiKeika += Z_pulseCheckSyuuki;
} else if (C_syuukiKeika < O_sound.syuuki) {
// kohan han syuuki
if (F_pwmSet == 1) {
F_pwmSet = 2;
D_soundOut = (float)pow(((double)O_sound.envelope / O_sound.shokichienvelope) , 2.0);
sound_out(D_soundOut, 1);
}
C_syuukiKeika += Z_pulseCheckSyuuki;
} else {
// jikai syuuki settei
F_pwmSet = 0;
C_syuukiKeika = 0;
}
// envelope jikan no kosin
if (O_sound.envelope > Z_pulseCheckSyuuki) {
O_sound.envelope -= Z_pulseCheckSyuuki;
} else {
O_sound.envelope = 0;
sound_out(0.0, 0);
}
}
else{
sound_out(0.0, 0);
}
_pwm.write(D_SPIpwm); // 2tuizyo sound out settei site ,interrupt no nakade renzoku de pwm set wo suruto bousou suru.
//*************************************************
// 1ms syuuki syori
//*************************************************
C_1msProcess++;
if((C_1msProcess * Z_pulseCheckSyuuki) > 1000){
C_1msProcess = 0;
sound_ensoSyori();
}
}
/******************************************************************************
Name : sound_sound()
Parameters : sound_t .hanon
: .onkai
: .time : hatuon jikan(1/1 [ms]/count)
: .envelope : yoin (1/1 [ms]/count)
Returns : none
Description : hitotu no oto no syuturyoku
******************************************************************************/
//*************************
// oto jyotai check
// ture : oto ari chu
// false: oto nasi chu
//*************************
bool Sound::sound_sound(void){
if (hatuon_jikan.read_ms() < keikajikan){
return(true);
}
else{
return(false);
}
}
//*************************
// oto syuturyoku
//*************************
void Sound::sound_sound(sound_t data) {
uint8_t onkai;
uint8_t okutabu;
uint8_t kaicho;
// oto no frequency // do re mi fa so ra si
const uint16_t DT_onkaiHzN[3][7] = {// C1 D1 E1 F1 G1 A1 B1 // frequency (1/1 [Hz]/count)
{30.8677, 34.6478, 38.8909, 41.2034, 46.2493, 51.9131, 58.2705}, // b
{32.7032, 36.7081, 41.2034, 43.6535, 48.9994, 55.0000, 61.7354}, // nomal
{34.6478, 38.8909, 43.6535, 46.2493, 51.9131, 58.2705, 65.4064}, // #
};
// onkai data kara DT_onkaiHzN[][koko] "koko" no number ni henkan
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
const uint8_t DT_onkaiTrans[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 1, 2, 3};
// tugi no hatuon siji
onkai = data.onkai;
okutabu = onkai & 0x0f;
kaicho = DT_onkaiTrans[(onkai & 0xf0) >> 4];
switch (onkai) {
case 0x00:
// enso chu (tugi no hatuon nasi settei)
// case 0xff to onaji syori
case 0xff:
// enso syuryo
O_sound.syuuki = 0; // muon
break;
default:
// enso chu & tugi no hatuon settei)
O_sound.syuuki = 1000000 / (DT_onkaiHzN[data.hanon][kaicho] * (pow(2.0, ((double)okutabu - 1))));
O_sound.envelope = data.envelope * 1000;
O_sound.shokichienvelope = data.envelope * 1000;
break;
}
// oto no syuturyoku jikan timer restart
hatuon_jikan.reset();
keikajikan = data.time;
}
/******************************************************************************
Name : sound_ensoSyori()
Parameters : none
Returns : none
Description : enso ji no tugino onpu data syutoku
******************************************************************************/
void Sound::sound_ensoSyori(void) {
// enso data settei
if((sound_sound() == false) // oto no syuturyoku jikan hantei
&& (onpu != NULL) // enso chu ka wo kakunin // 120115 bug fix
){
// tugi no onpu data syutoku
sound_t data = *onpu;
if(data.onkai == 0xff){
onpu = NULL;
}
else{
// tugi no hatuon siji
sound_sound(data);
onpu++;
}
}
}
/******************************************************************************
Name : sound_enso()
Parameters : -
Returns : -
Description : -
******************************************************************************/
//***********************************************************
// load enso data(mbed drive)
// Parameter : "/local/enso.txt" (data name = enso.txt)
//***********************************************************
bool Sound::sound_enso(char *path) {
int32_t ans;
// file open
FILE *stm = fopen(path,"r");
if(stm == NULL){
return (false);
}
// enso data set
uint8_t i = 0;
do{
ans = fscanf(stm, "%x%d%d", &enso[i].onkai, &enso[i].time, &enso[i].envelope);
i++;
}while((ans != EOF) & (i < 100));
fclose(stm);
ensoDataTable = enso;
return (true);
}
//***********************************************************************
// load enso data(program data table)
// Parameter : (Sound::sound_t*)DEMEKIN (data table name = DEMEKIN)
//***********************************************************************
void Sound::sound_enso(Sound::sound_t* onpudata) {
ensoDataTable = onpudata;
}
//*************************
// enso jyotai check
// ture : enso chu
// false: enso syuryo
//*************************
bool Sound::sound_enso(void) {
bool ans;
if(onpu != NULL){
ans = true;
}
else{
ans = false;
}
return (ans);
}
//*******************
// enso start / stop
// true : start
// false: stop
//*******************
void Sound::sound_enso(bool siji){
if(siji == true){
hatuon_jikan.reset(); // 120108 bug fix
keikajikan = 0; // 120115 bug fix
onpu = (sound_t*)ensoDataTable;
}
else{
onpu = NULL;
}
}
/******************************************************************************
Name : enso data sample
Parameters : -
Returns : -
Description : -
******************************************************************************/
/*
//------------------------------
// "demekin no uta" merody data
//------------------------------
const sound_t DEMEKIN[] = {
// onkai,hatuon jikan[ms]
{1,0xC5,600,500}, // de
{1,0xE5,600,500}, // me
{1,0x95,600,500}, // kin
{1,0x00,600,500},
{1,0xC5,600,500}, // de
{1,0xE5,600,500}, // me
{1,0x95,600,500}, // kin
{1,0x00,600,500},
{1,0xC5,600,500}, // de
{1,0xE5,600,500}, // me
{1,0x95,600,500}, // kin
{1,0x95,600,500}, // no
{1,0x95,150,500}, // shi
{1,0x00,900,500},
{1,0xE5,750,500}, // po
{1,0x00,450,500},
{1,0xC5,600,500}, // de
{1,0xE5,600,500}, // me
{1,0x95,600,500}, // kin
{1,0x00,600,500},
{1,0xC5,600,500}, // de
{1,0xE5,600,500}, // me
{1,0x95,600,500}, // kin
{1,0x00,600,500},
{1,0x95,600,500}, // ju
{1,0xE5,600,500}, // go
{1,0xD5,600,500}, // n
{1,0xC5,600,500}, // no
{1,0xE5,150,500}, // shi
{1,0x00,900,500},
{1,0xC5,750,500}, // po
{1,0x00,1350,500},
{1,0xFF,0,0}, // end
};
//---------------------------------
// "westminster chime" merody data
//---------------------------------
const sound_t WESTMINSTER[] = {
// onkai,hatuon jikan[ms]
{1,0xA4,1200,1000},
{1,0xF4,1200,1000},
{1,0x94,1200,1000},
{1,0xC4,2400,1000},
{1,0xC4,1200,1000},
{1,0x94,1200,1000},
{1,0xA4,1200,1000},
{1,0xF4,2400,1000},
{1,0xFF,0,0}, // end
};
//------------------------------
// "ramen chime" merody data
//------------------------------
const sound_t RAMEN[] = {
// onkai,hatuon jikan[ms]
{1,0xC5,300,500},
{1,0xD5,300,500},
{1,0xE5,1200,500},
{1,0xD5,600,500},
{1,0xC5,1200,500},
{1,0xC5,300,500},
{1,0xD5,300,500},
{1,0xE5,300,500},
{1,0xD5,300,500},
{1,0xC5,300,500},
{1,0xD5,1800,500},
{1,0xFF,0,0}, // end
};
*/