📄 core.c
字号:
#ifdef _AVR_PWM_
TCCR1A &= ~(BV(COM1B1)); // Disable PWM
DDRB &= ~(BV(PB2)); // make B2 an input pin
#endif
#ifdef _AVR_BINARY_
SOUND_DDR &= ~(SOUND_BIT); // Set speaker port as input
#endif
#ifdef _AVR_QUAD_
QUAD_DDR &= ~(QUAD_MASK); // Set ports as input
#endif
#endif
}
void soundOn(void){
#ifdef _AVR_
#ifdef _AVR_PWM_
DDRB |= BV(PB2); // make B2 an output pin
TCCR1A = 0; // disable PWM
ICR1 = PWM_TOP;
TCCR1B = PWM_FLAGS;
TCNT1=0;
TCCR1A |= BV(COM1B1); // ENABLE PWM ON B2 USING OC1B, OCR1B
#endif
#ifdef _AVR_BINARY_
SOUND_DDR |= (SOUND_BIT); // Set speaker port as output
SOUND_PORT &= ~(SOUND_BIT);
#endif
#ifdef _AVR_QUAD_
QUAD_DDR |= (QUAD_MASK); // Set ports as output
QUAD_PORT &= ~(QUAD_MASK); // all off
#endif
// initialise random number seed
seed0=0xecu;
seed1=7;
seed2=0xcfu;
#endif
}
#ifdef _AVR_PWM_
// Logarithmic scale
//static const int16_t PROGMEM Volume[8] = {0,PWM_TOP * 0.01,PWM_TOP * 0.02,PWM_TOP * 0.03,PWM_TOP * 0.06,PWM_TOP * 0.12,PWM_TOP * 0.25,PWM_TOP * 0.5};
// Linear scale
static const int16_t PROGMEM Volume[8] = {0,PWM_TOP * 0.07,PWM_TOP * 0.14,PWM_TOP * 0.21,PWM_TOP * 0.29,PWM_TOP * 0.36,PWM_TOP * 0.43,PWM_TOP * 0.5};
#endif
void sound(uint8_t b){
b = (b & 15);
#ifdef _LOG_
loggerc((char)(b+'0'));
#endif
#ifdef _AVR_
#ifdef _AVR_PWM_
// Update PWM volume
int16_t duty = pgm_read_word(&Volume[b>>1]); // get duty cycle
if(duty!=OCR1B){
TCNT1=0;
OCR1B = duty;
}
#endif
#ifdef _AVR_BINARY_
// Update Port Volume
if(b>=8){
SOUND_PORT |= SOUND_BIT;
}else{
SOUND_PORT &= ~(SOUND_BIT);
}
#endif
#ifdef _AVR_QUAD_
b <<= QUAD_BIT;
b &= QUAD_MASK;
QUAD_PORT = (QUAD_PORT & ~(QUAD_MASK)) | b;
#endif
#endif
}
uint8_t playTone(uint8_t soundNum,uint8_t soundPos,char pitch1, char pitch2, uint8_t count, uint8_t volume){
const uint8_t* soundData = &SoundData[soundNum * 0x40];
while(count-- > 0 ){
uint8_t s;
s = pgm_read_byte(&soundData[soundPos & 0x3fu]);
sound((uint8_t)(s & volume));
pause(pitch1);
sound((uint8_t)((s>>4) & volume));
pause(pitch2);
soundPos++;
}
return soundPos & 0x3fu;
}
void play(uint8_t duration, uint8_t soundNumber){
while(duration-- != 0){
playTone(soundNumber,random(), 7,7, 10, 15);
}
}
void setPitch(uint8_t pitch){
default_pitch = pitch;
}
/*
* Speak a string of phonemes
*/
void speak(const char* textp){
uint8_t
phonemeIn, // offset into text
byte2,
modifierIn, // offset into stuff in modifier
punctuationPitchDelta; // change in pitch due to fullstop or question mark
char byte1;
char phoneme;
const SOUND_INDEX* soundIndex;
uint8_t sound1Num; // Sound data for the current phoneme
uint8_t sound2Num; // Sound data for the next phoneme
uint8_t sound2Stop; // Where the second sound should stop
char pitch1; // pitch for the first sound
char pitch2; // pitch for the second sound
short i;
uint8_t sound1Duration; // the duration for sound 1
if(phonemesToData(textp,s_phonemes)){
// phonemes has list of sound bytes
#ifdef _LOG_
loggerP(PSTR("Data:"));
logger(phonemes);
loggerCRLF();
#endif
soundOn();
// _630C
byte1=0;
punctuationPitchDelta=0;
//Q19
for(phonemeIn=0,modifierIn=0;phonemes[phonemeIn]!=0; phonemeIn+=2, modifierIn+=2){
uint8_t duration; // duration from text line
uint8_t SoundPos; // offset into sound data
uint8_t fadeSpeed=0;
phoneme=phonemes[phonemeIn];
if(phoneme=='z'){
delay(15);
continue;
}else if(phoneme=='#'){
continue;
}else{
// Collect info on sound 1
soundIndex = &SoundIndex[phoneme - 'A'];
sound1Num = pgm_read_byte(&soundIndex->SoundNumber);
byte1 = pgm_read_byte(&soundIndex->byte1);
byte2 = pgm_read_byte(&soundIndex->byte2);
duration = phonemes[phonemeIn+1] - '0'; // Get duration from the input line
if(duration!=1){
duration<<=1;
}
duration += 6; // scaled duration from the input line (at least 6)
sound2Stop = 0x40>>1;
pitch1 = modifier[modifierIn];
if(modifier[modifierIn + 1]==0 || pitch1==-1){
pitch1 = 10;
duration -= 6;
}else if(modifier[modifierIn + 1]=='0' || duration==6){
duration -= 6;
}
//q8
pitch2 = modifier[modifierIn+2];
if(modifier[modifierIn + 3]==0 || pitch2 == -1){
pitch2 = 10;
}
//q10
if(byte1<0){
sound1Num = 0;
random();
sound2Stop=(0x40>>1)+2;
}else{
// is positive
if(byte1==2){
// 64A4
// Make a white noise sound !
uint8_t volume; // volume mask
#ifdef _LOG_
loggerP(PSTR("\nA *******"));
logger_uint8(duration);
loggerCRLF();
#endif
volume = (duration==6) ? 15 : 1; /// volume mask
for(duration <<= 2; duration>0; duration--){
playTone(sound1Num,random(),8,12,11, volume);
// Increase the volume
if(++volume==16){
volume = 15; // full volume from now on
}
}
continue;
}else{
//q11
if(byte1 != 0){
delay(25);
}
}
}
}
// 6186
pitch1 += default_pitch + punctuationPitchDelta;
if(pitch1<1){
pitch1=1;
}
pitch2 += default_pitch + punctuationPitchDelta;
if(pitch2<1){
pitch2=1;
}
// get next phoneme
phoneme=phonemes[phonemeIn + 2];
if(phoneme==0 || phoneme=='z'){
if(duration==1){
delay(60);
}
phoneme='a'; // change to a pause
}else{
// s6
if(byte2 != 1){
byte2 = (byte2 + pgm_read_byte(&SoundIndex[phoneme-'A'].byte2))>>1;
}
if(byte1 < 0 || pgm_read_byte(&SoundIndex[phoneme-'A'].byte1) != 0){
phoneme ='a'; // change to a pause
}
}
// S10
sound2Num = pgm_read_byte(&SoundIndex[phoneme-'A'].SoundNumber);
sound1Duration = 0x80; // play half of sound 1
if(sound2Num==sound1Num){
byte2 = duration;
}
// S11
if( (byte2>>1) == 0 ){
sound1Duration = 0xff; // play all of sound 1
}else{
// The fade speed between the two sounds
fadeSpeed = (sound1Duration + (byte2>>1))/byte2;
if(duration==1){
sound2Stop = 0x40; // dont play sound2
sound1Duration = 0xff; // play all of sound 1
pitch1 = 12;
}
}
SoundPos = 0;
do{
uint8_t sound1Stop = (sound1Duration>>2) & 0x3fu;
uint8_t sound1End = min(sound1Stop , sound2Stop);
if( sound1Stop != 0 ){
#ifdef _LOG_
loggerP(PSTR("\nB Remaining="));
logger_uint8(duration);
loggerP(PSTR("Repeat min("));
logger_uint8(sound1Stop);
loggerP(PSTR(","));
logger_uint8(sound2Stop);
loggerP(PSTR(") times,Sound#="));
loggerc((char)(sound1Num+'A'));
loggerP(PSTR("["));
logger_uint8(SoundPos);
loggerP(PSTR("]\n"));
#endif
SoundPos = playTone(sound1Num,SoundPos,pitch1,pitch1, sound1End, 15);
}
// s18
if(sound2Stop != 0x40){
#ifdef _LOG_
loggerP(PSTR("\nC Remaining="));
logger_uint8(duration);
loggerP(PSTR("Repeat "));
logger_uint8((uint8_t)(sound2Stop-sound1End));
loggerP(PSTR(" times,Sound#="));
loggerc((char)(sound2Num+'A'));
loggerP(PSTR("["));
logger_uint8(SoundPos);
loggerP(PSTR("]\n"));
#endif
SoundPos = playTone(sound2Num,SoundPos,pitch2,pitch2, (uint8_t)(sound2Stop - sound1End), 15);
}
//s23
if(sound1Duration!=0xff && duration<byte2){
// Fade sound1 out
sound1Duration -= fadeSpeed;
if( sound1Duration >= (uint8_t)0xC8){
sound1Duration=0; // stop playing sound 1
}
}
// Call any additional sound
if(byte1==-1){
play(3,30); // make an 'f' sound
}else if(byte1==-2){
play(3,29); // make an 's' sound
}else if(byte1==-3){
play(3,33); // make a 'th' sound
}else if(byte1==-4){
play(3,27); // make a 'sh' sound
}
}while(--duration!=0);
// Scan ahead to find a '.' or a '?' as this will change the pitch
punctuationPitchDelta=0;
for(i=6; i>0; i--){
char next = phonemes[phonemeIn + (i * 2)];
if(next=='i'){
// found a full stop
punctuationPitchDelta = 6 - i; // Lower the pitch
}else if(next=='h'){
// found a question mark
punctuationPitchDelta = i - 6; // Raise the pitch
}
}
if(byte1 == 1){
delay(25);
}
} // next phoneme
}
soundOff();
}
/*
* Speak an English command line of text
*/
void say(const char * original){
int i;
if(textToPhonemes(original,s_vocab, phonemes)){
#ifdef _LOG_
loggerP(PSTR("Say:'"));
logger(original);
loggerP(PSTR("' => Phonemes:'"));
logger(phonemes);
loggerCRLF();
#endif
// copy string from phonemes to text
for(i = 0;phonemes[i]!=0;i++){
g_text[i]=phonemes[i];
}
while(i<sizeof(g_text)){
g_text[i++]=0;
}
speak(g_text);
}
}
void init(void){
#ifdef _AVR_
uartInit(); // initialize the UART (serial port)
uartSetBaudRate(19200);// set the baud rate of the UART for our debug/reporting output
rprintfInit(uartSendByte);// initialize rprintf system
// Power save
PRR = BV(PRTWI) // turn off TWI
| BV(PRSPI) // turn off SPI
| BV(PRADC) // turn off ADC
| BV(PRTIM0) // turn off TIMER0
| BV(PRTIM2) // turn off TIMER2
;
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -