📄 ring.cpp
字号:
#include "defines.h"
#include "Ring.h"
/*
铃声代码表:
255: 音乐结束,重新演奏
254: 循环开始
253: 循环结束
252: 调用子串,后接子串地址
251: 子串返回
250: 音乐跳转,后接跳转地址
>128:设置音长,音长=(该数-128)/16 (拍)
128: 音乐结束,不重新演奏
<128:设置音符,高4位选择哪组音,低4位0-C分别代表0,1,1#,2,2#,3,4,4#,5,5#,6,6#,7
1 2 3 4 5 6 7 8 9 a b c
例:21h代表主音1
*/
const UCHAR *CRing::m_cur_addr; //当前乐谱在内存的位置
UCHAR CRing::m_cur_length; //当前音长
UCHAR CRing::m_note_length; //乐谱最后一次设置的音长
UCHAR CRing::m_stack_deep; //栈的位置
UCHAR CRing::m_done_deep; //辅助栈的位置
UCHAR CRing::m_loop_stack[10]; //循环栈
UCHAR CRing::m_loop_done[10]; //循环辅助栈
UCHAR CRing::m_cur_index; //乐谱当前位置
USHORT CRing::m_time; //已经播放的节拍数
//嘀嘀嘀嘀----嘀嘀嘀嘀----
const UCHAR music0[] = {128+1, 254, 0x31, 0, 0x31, 0, 253, 128+8 , 0, 255};
//1, 2, 3, 4, 5, 6, 7
const UCHAR music1[] = {128+16, 254,
0x21, 0x23, 0x25, 0x26, 0x28, 0x2a, 0x2c,
253, 255};
const UCHAR *MUSIC[] = {music0, music1};
#define SetTimer1freq(freq)\
{\
OCR1A = 1000000 / (2 * freq);\
TCNT1 = 0xffff - (1000000 / (2 * freq)) +1;\
}
#define isTimer1Busy (TCCR1B & 0x07)
#define OpenTimer1() {TCCR1A = 0x40; TCCR1B = 9;}
#define CloseTimer1() {TCCR1A = 0x00; TCCR1B = 0; PORTB &= ~2;}
// 1/16节拍
void CRing::OnTick()
{
if(!(m_time || m_cur_addr)) return;
if(!m_cur_addr){//现在是在Beep
if(!--m_time)
CloseTimer1();
return;
}
if(++m_time == 16 * 60){
//播放了一分钟后自动停止
StopRing();
return;
}
if(--m_cur_length) return;
for(;;){
UCHAR note = m_cur_addr[m_cur_index++];
if(note == 254){//循环开始
m_loop_done[m_done_deep++] = 0;//第一遍播放
m_loop_stack[m_stack_deep++] = m_cur_index;
}else if(note == 253){//循环结束
if(m_loop_done[m_done_deep-1]){
//第二遍播放完毕
m_done_deep--;
}else{
m_loop_done[m_done_deep-1] = 1; //第二遍播放
m_cur_index = m_loop_stack[--m_stack_deep];
}
}else if(note == 252){//调用子串
m_loop_stack[m_stack_deep++] = m_cur_index + 1;
m_cur_index = m_cur_addr[m_cur_index];
}else if(note == 251){//子串返回
m_cur_index = m_loop_stack[--m_stack_deep];
}else if(note == 250){//音乐跳转
m_cur_index = m_cur_addr[m_cur_index];
}else if(note == 255){
m_cur_index = 0;
m_stack_deep = 0;
m_done_deep = 0;
}else if(note == 128){//停止
StopRing();
break;
}else if(note < 128){//真正的音符
SetNote(note);
m_cur_length = m_note_length;
break;
}else if(note > 128){//音长
m_note_length = note & 0x7f;
}
}
}
//播放铃声
void CRing::Play(UCHAR index, UCHAR repeat)
{
m_cur_addr = MUSIC[index];//当前乐谱在内存的位置
m_cur_length = 1; //当前音长
m_note_length = 0; //乐谱最后一次设置的音长
m_stack_deep = 0; //栈的位置
m_done_deep = 0; //辅助栈的位置
m_cur_index = 0; //乐谱当前位置
OpenTimer1();
OnTick();
m_time = 0; //已经播放的节拍数
}
void CRing::Beep(USHORT freq, UCHAR note16)
{
if(!isTimer1Busy){
SetTimer1freq(freq);
OpenTimer1();
m_time = note16;
m_cur_addr = 0;
}
}
void CRing::SetNote(UCHAR note)
{
static USHORT delay[]={0,
3817, 3610, 3401, 3215,
3030, 2865, 2703, 2551,
2410, 2273, 2146, 2024};
if(note & 0x0f){
if(!isTimer1Busy) OpenTimer1();
USHORT data = delay[note & 0x0f];
data >>= (note >> 4);
OCR1A = data;
TCNT1 = 1 + ~data;
}else{
//不要忘记,乐谱里还有休止符
TCCR1B = 0;
PORTB &= ~2; //Timer停止的时候,PB1的电平时随机的,为了省电,把它置低
}
}
UCHAR CRing::GetCount()
{
return sizeof(MUSIC) / sizeof(UCHAR*);
}
void CRing::StopRing()
{
CloseTimer1();
m_cur_addr = NULL;
m_time = 0;
}
UCHAR CRing::IsPlayingRing()
{
return m_cur_addr != NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -