📄 project.c
字号:
PORTB &= ~DF_CHIP_SELECT; //Enable Flash
if (active_buffer == 1) { //Transfer page to inactive buffer
WRITE_SPI (MM_PAGE_TO_B2_XFER);
}
else {
WRITE_SPI (MM_PAGE_TO_B1_XFER);
}
if (buffer_max == 528) {
WRITE_SPI (page_counter >> 6); //Write first part of page counter
WRITE_SPI (page_counter << 2); //Write next part of page counter
}
else {
WRITE_SPI (page_counter >> 7); //Write first part of page counter
WRITE_SPI (page_counter << 1); //Write next part of page counter
}
WRITE_SPI (0x00); //Dont care bits
PORTB |= DF_CHIP_SELECT; //Disable the DataFlash
}
//Retrieves the contents of the active buffer in the DataFlash and writes it
//to the PWM module in sync. with the sampling frequency.
void active_buffer_to_speaker (unsigned char active_buffer) {
unsigned int buffer_counter = 0;
unsigned char temp = 0x80;
PORTB &= ~DF_CHIP_SELECT; //Enable Flash
if (active_buffer == 1) { //Transfer page to inactive buffer
WRITE_SPI (BUFFER_1_READ); //Command to read buffer 1
}
else {
WRITE_SPI (BUFFER_2_READ); //Command to read buffer 2
}
WRITE_SPI (0x00); //Dont care bits
WRITE_SPI (0x00); //Dont care bits
WRITE_SPI (0x00); //Dont care bits
WRITE_SPI (0x00); //Dont care bits
while (buffer_counter < buffer_max) { //As long as buffer is not done...
while (!sync); //Wait for synchronization
sync = 0; //Clear the sync.
SPDR = 0xFF; //Send a Dummy value
while (!(SPSR & temp)); //Wait for transfer
OCR1B = SPDR; //Write to PWM module
buffer_counter++; //increment buffer pos.
}
PORTB |= DF_CHIP_SELECT; //Disable the DataFlash
}
//Retrieves digital audio from the DataFlash and plays it back on the speaker.
void playback (void) {
unsigned int page_counter = 0;
unsigned int buffer_counter = 0;
unsigned char active_buffer = 1;
unsigned char temp = 0x80;
enable_PWM ();
enable_timer0 ();
SPCR = 0x5C; //Enable SPI, master mode, MSB first,
//SPI mode 3, 2MHz clock
reset_rec = 1;
//Read first page to buffer
next_page_to_next_buffer (active_buffer, page_counter);
while (!(PINB & 0x02)); //Wait for Flash to be ready
sync = 0;
while (!(PIND&0x01) || lock) { //While play is pressed
if (page_counter < 4096) {
page_counter++; //Read from the next page
//Copy the next page into the inactive buffer
next_page_to_next_buffer (active_buffer, page_counter);
//Play the active buffer
active_buffer_to_speaker (active_buffer);
//swap buffers
if (active_buffer == 1) active_buffer++;
else active_buffer--;
}
else {
//TODO:
//Indicate that the end is reached
led_state |= 0x01;
}
if (lock) {
if (!(PIND&0x08)) lock = 0;
led_state |= 0x08;
}
else {
if (!(PIND&0x08)) lock = 1;
led_state &= ~0x08;
}
}
lock = 0;
TCCR0 = 0x00; //Disable Timer0
TCCR1B = 0x00; //Disable Timer1PWM
SPCR = 0x00; //Disable SPI
PORTC = 0xFF; //Turn off LEDs
}
//Records digital audio from the mike and stores it in the DataFlash
void record (void) {
static unsigned int page_counter = 0;
static unsigned int buffer_counter = 0;
static unsigned char active_buffer = 1;
static unsigned char temp = 0x80;
if (ACSR&0x02) { //ACSR bit 1 is used to determine if data has
//been erased (ie, start from previous point
//or from start of memory)
buffer_counter = 0; //If ACSR has been set, make the position vars.
page_counter = 0; //point to the beginning of Flash
ACSR &= 0xFD; //Clear the flag
active_buffer = 1; //Make Buffer 1 active.
}
if (reset_rec) { //If some other function is called after
//the previous record session, align the
//new data to a page boundary and reset the
//active buffer.
active_buffer = 1; //Set active buffer to 1
buffer_counter = 0; //Clear buffer pos.
reset_rec = 0; //Make sure this happens only once per session.
}
init_ADC ();
enable_timer0 ();
SPCR = 0x5D; //Enable SPI, master mode, MSB first,
//SPI mode 3, 2MHz clock
while (!(PIND&0x02) || lock) { //As long as record is pressed...
if (page_counter < 4096) {
page_counter++; //Read from the next page
prev_page_to_prev_buffer (active_buffer, page_counter);
//Play the active buffer
adc_to_active_buffer (active_buffer);
//swap buffers
if (active_buffer == 1) active_buffer++;
else active_buffer--;
}
else {
//TODO:
//Indicate that the end is reached
led_state |= 0x02;
}
if (lock) {
if (!(PIND&0x08)) lock = 0;
led_state |= 0x08;
}
else {
if (!(PIND&0x08)) lock = 1;
led_state &= ~0x08;
}
}
TCCR0 = 0x00; //Disable Timer0
SPCR = 0x00; //Stop SPI
PORTC = 0xFF; //Turn off all LEDs.
}
//Erases the DataFlash and resets the recording position to the start of the
//DataFlash memory.
void erase (void) {
int block_counter = 0;
unsigned char temp = 0x80;
ACSR |= 0x02; //Indicates that recording is to start from beginning
//of flash, and not from where it was left off last.
SPCR = 0x5C; //Enable SPI
min_val = 0x1FF;
while (block_counter < 512) {
PORTB &= ~DF_CHIP_SELECT; //Select Flash
WRITE_SPI (BLOCK_ERASE); //Write command
if (buffer_max == 528) {
WRITE_SPI (block_counter >> 3); //Which block to erase
WRITE_SPI (block_counter << 5);
}
else {
WRITE_SPI (block_counter >> 4);
WRITE_SPI (block_counter << 4);
}
WRITE_SPI (0x00); //Dont care value
PORTB |= DF_CHIP_SELECT; //Deselect Flash
block_counter++;
while (!(PINB & 0x02));
}
SPCR = 0x00; //Disable SPI
led_state = 0x04; //Enable Blinking erase LED.
while (!(PIND&0x04)); //Wait till user releases Erase key
//Short pause, for debouncing
for (block_counter = 0; block_counter < 10000; block_counter++);
PORTC = 0xFF; //Turn off all LEDs.
}
//Loops the audio from the mike to the speaker.
void loopback (void) {
unsigned char t;
enable_PWM ();
init_ADC ();
enable_timer0 ();
min_val = 0xFF;
while (!(PIND&0x08)){ //Wait till the user lets go of the key
OCR1BL = (adc_value - min_val) >> 1;
/*
t = mu_table [abs(adc_value - 533)];
if (adc_value < 533) OCR1BL = 128 - t;
else OCR1BL = t + 128;
*/
ADCSR = 0xC9;
while (!sync);
sync = 0;
if ((PIND&0x03)!=0x03) break;
}
TCCR0 = 0x00; //Disable Timer0
TCCR1B=0x00; //Disable Timer1 (PWM)
PORTC = 0xFF; //Turn off all LEDs.
}
//This function generates a short beep at ~2000Hz.
void beep (void) {
int i;
unsigned char c = 64; //initial value of C
enable_PWM ();
enable_timer0 ();
for (i = 0; i < 400; i++) {
OCR1B = c; //write value to PWM
while (!sync); //Wait for sync 4 times (2000Hz)
sync = 0;
while (!sync);
sync = 0;
while (!sync);
sync = 0;
while (!sync);
sync = 0;
c = 192 - c; //invert the value of c
}
TCCR1B = 0x00; //Stop PWM
TCCR0 = 0x00; //Stop timer0
}
//Retrieves the chip ID of the attached DataFlash and sets the maximum buffer
//size. In case an SPI error occurs (missing/damaged DataFlash), a long beep
//is sounded and the Voice Recorder functions are disabled.
void get_chip_id (void) {
unsigned char temp = 0x80;
PORTB &= ~DF_CHIP_SELECT; //Enable Flash
SPCR = 0x5C; //Enable SPI
WRITE_SPI (STATUS_REGISTER); //Write command to retrieve status register
WRITE_SPI (0xFF); //Write dummy value
PORTC = ~(SPDR >> 3); //Show the device code on LEDs at startup
if ((SPDR & 0x38)==0x20) {
buffer_max = 264; //Set buffer length for AT45DB081A
}
else if ((SPDR & 0x38)==0x28) {
buffer_max = 528; //Set buffer length for AT45DB081A
}
else { //An error has occured... missing Flash?
beep (); //Long beep
beep ();
led_state = 0x0F; //Make LEDs flash
for (;;); //Prevent further use till reset.
}
SPCR = 0x00; //Disable SPI
PORTB |= DF_CHIP_SELECT; //Deselect Flash
}
//Main function
void main () {
setup ();
//Set up Timer 2 (used to flash LEDs)
ASSR = 0x00; //set async mode
TCCR2 = 0x07; //Enable Timer2 with prescaler set to /8
TIMSK |= 0x40; //Enable Timer2 interrupt in mask register
get_chip_id (); //Get the ident. of memory attached.
beep (); //Signal to the user that device is ready
for (;;) {
led_state = 0x00; //Stop all LEDs from flashing.
if(!(PIND&0x01)) { //If play key is pressed,
if (!(PIND&0x08)) lock = 1;
PORTC = 0xFE; //Light up the play LED...
playback (); //...and start playback.
}
if(!(PIND&0x02)) { //If record key is pressed,
if (!(PIND&0x08)) lock = 1;
PORTC = 0xFD; //Light up record LED...
record (); //...and start recording.
}
if(!(PIND&0x04)) { //If erase key is pressed,
PORTC = 0xFB; //Light up erase LED...
erase(); //...and start erasing.
}
if(!(PIND&0x08)) { //Do loopback if loopback key is pressed.
PORTC = 0xF7;
loopback();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -