⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 f411_vr.c

📁 用c8051f410和FLASH(SPI接口)实现的数字录音机。
💻 C
📖 第 1 页 / 共 3 页
字号:
      }
      // the REC_PLAY switch was not pressed
      else
      {
         // clear the END_MEM recording flag after the ADC ISR has turned off
         // the ADC
         if ((system_state & END_MEM) == END_MEM)
         {
            system_state &= ~RECORDING;
         }

         // the system is currently recording - stop recording
         if (system_state == RECORDING)
         {
            system_state &= ~RECORDING;
            ADC_STOP_FLAG = 1;         // notify the ADC to stop recording

            MEM_END_NEAR_FLAG = 0;     // clear all flags
            MEM_END_FLAG = 0;

            LED_DCH = &LED0_DC;        // point to the record LED's duty cycle
                                       // address
            Dim_LED ();                // dim off the record LED
         }

         // check if the playback has reached the end of the recording
         if (REC_END_FLAG == 1)
         {
            // stop playing
            system_state &= ~PLAYING;
            REC_END_FLAG = 0;

            LED_DCH = &LED1_DC;        // point to the play LED's duty cycle
                                       // address
            Dim_LED ();                // dim off the play LED
         }
      }
   }

   // ERASE button pressed
   if (ERASE == 0)
   {
      // do nothing if the device is currently recording or playing
      // ignore the ERASED and END_MEM bits
      if ((system_state & 0x03) == IDLE)
      {
         // Indicate to the user that the microcontroller is busy
         LED_DCH = &LED1_DC;
         Brighten_LED ();
         LED_DCH = &LED0_DC;
         Brighten_LED ();

         rec_end_addr = 0x00000000;    // reset the counter
         system_state |= ERASED;       // set the erase bit
         Erase_MEM ();                 // erase the external SST Flash

         LED_DCH = &LED1_DC;
         Dim_LED ();
         LED_DCH = &LED0_DC;
         Dim_LED ();
      }

      switch_pressed_flag = 1;         // record the user interaction
   }

   if (switch_pressed_flag == 0)
   {
      // check if the recorder is sitting and idle
      // ignore the ERASED and END_MEM bits
      if ((system_state & 0x03) == IDLE)
      {
         suspend_counter++;

         // if no interaction occurs in 5 seconds, enter suspend mode
         if (suspend_counter == 320)
         {
            suspend_counter = 0;
            ENTER_SUSPEND = 1;
         }
      }
   }
   else
   {
      suspend_counter = 0;             // reset the SUSPEND mode counter
                                       // if the user is interacting with the
                                       // recorder

      reload_value = PRCHANGE;         // interrupt again in 150 ms
   }

   // reload the timer for the next interrupt
   TL1 = (-reload_value) & 0x00FF;
   TH1 = ((-reload_value) & 0xFF00) >> 8;
}

//-----------------------------------------------------------------------------
// ADC0_ISR
//-----------------------------------------------------------------------------
//
// Handle the 8kHz Timer 2 interrupt.
//
// Timer 2 controls the rate at which the ADC samples the input (RECORD).
//
void ADC0_ISR (void) interrupt 10 using 2
{
   // RECORD

   // DPCM variables
   static data unsigned short predicted_value = mid_range;
   static data unsigned char packed_code = 0x00;
   data unsigned char dpcm_code = 0x00;

   // indicates how the current dpcm_code should be packed to be sent to memory
   // sample 1 dpcm_code = A, sample 2 dpcm_code = B, sample 3 dpcm_code = C
   // sample 4 dpcm_code = D, sample 5 is the same as sample 1, etc
   // [A|A|A|A|A|A|B|B] = byte 1
   // [B|B|B|B|C|C|C|C] = byte 2
   // [C|C|D|D|D|D|D|D] = byte 3
   static unsigned char state = 0;

   static short sample = 0x0000;

   AD0INT = 0;                         // clear the interrupt flag

   // check if the memory was erased
   if ((system_state & ERASED) == ERASED)
   {
      system_state &= ~ERASED;         // clear the erased bit
      predicted_value = mid_range;     // reset the dpcm predictor
      state = 0;                       // reset the packing state machine
   }

   // check for the end of memory
   if (rec_end_addr == MAX_MEM_ADDR)
   {
      TR2 = 0;                         // turn off T2
      MEM_END_NEAR_FLAG = 0;
      MEM_END_FLAG = 1;                // tell the T1 ISR to turn off the LED
      predicted_value = mid_range;     // reset the dpcm predictor
      state = 0;                       // reset the state machine
   }
   else
   {
      // check if the REC_PLAY switch was released and the recording should
      // stop
      if (ADC_STOP_FLAG == 1)
      {
         TR2 = 0;                      // turn off T2
         ADC_STOP_FLAG = 0;            // reset the flag

         // do not reset the state or the predicted_value variables here
         // the playback ISR doesn't know when a recording starts or ends,
         // so it will also not reset the state and predicted_value
      }
      // take the sample, average it, compress it, and send it to memory
      else
      {
         // since 16 samples are automatically accumulated by the ADC,
         // average them by dividing by 16 (right shifting by 4)
         sample = (ADC0DAT >> 4) & 0x0FFF;



         // calculate the difference between the sample and the predictor
         // and compress the sample to a 6-bit DPCM code
         dpcm_code = DPCM_Encode ((sample - predicted_value));

         // pack the DPCM code into the bytes sent to the Flash memory
         switch (state)
         {
             // state machine: 0 -> 1 -> 2 -> 3
             //                ^______________|
             case 0:

               // move the DPCM code into the 6 high bits
               // [A|A|A|A|A|A| | ] = byte 1
               packed_code = (dpcm_code << 2) & 0xFC;

               state = 1;
               break;

             case 1:

               // move the DPCM code into the 2 low bits
               // of the previously packed byte
               // [-|-|-|-|-|-|B|B] = byte 1

               packed_code |= (dpcm_code >> 4) & 0x03;

               Write_MEM (rec_end_addr, packed_code);
               rec_end_addr++;

               // move the rest of the DPCM code into the
               // 4 high bits of the next packed byte
               // [B|B|B|B| | | | ] = byte 2

               packed_code = (dpcm_code << 4) & 0xF0;

               state = 2;
               break;

             case 2:

               // move the next DPCM code into the
               // 4 low bits of the previously packed byte
               // [-|-|-|-|C|C|C|C] = byte 2

               packed_code |= (dpcm_code >> 2) & 0x0F;

               Write_MEM (rec_end_addr, packed_code);
               rec_end_addr++;

               // move the rest of the DPCM code into the
               // 2 high bits of the next packed byte
               // [C|C| | | | | | ] = byte 3

               packed_code = (dpcm_code << 6) & 0xC0;

               state = 3;
               break;

             case 3:

               // move the next DPCM code into the
               // 6 low bits of the previously packed byte
               // [-|-|D|D|D|D|D|D] = byte 3

               packed_code |= dpcm_code & 0x3F;

               Write_MEM (rec_end_addr, packed_code);
               rec_end_addr++;

               state = 0;
               break;

             default:
               state = 0;
               break;
         }

         // indicate that the T1 ISR should flutter the LED, since the end of
         // memory is close
         if (rec_end_addr == NEAR_END_ADDR)
         {
            MEM_END_NEAR_FLAG = 1;
         }

         // update the predictor for the next sample
         predicted_value += DPCM_Decode (dpcm_code);
      }
   }
}

//-----------------------------------------------------------------------------
// Timer3_ISR
//-----------------------------------------------------------------------------
//
// Handle the 8kHz Timer 3 interrupt.
//
// Timer 3 controls the rate at which the DAC outputs decompressed samples
// (PLAY).
//
void Timer3_ISR(void) interrupt 14 using 2
{
   // PLAY

   // next unwritten address
   static unsigned long current_play_addr = 0x00000000;

   // DPCM variables
   static unsigned short predicted_value = mid_range;
   static unsigned char packed_code = 0x00;
   unsigned char dpcm_code = 0x00;

   // indicates how the current dpcm_code should be unpacked when retrieved
   // from memory
   // sample 1 dpcm_code = A, sample 2 dpcm_code = B, sample 3 dpcm_code = C
   // sample 4 dpcm_code = D, sample 5 is the same as sample 1, etc
   // [A|A|A|A|A|A|B|B] = byte 1
   // [B|B|B|B|C|C|C|C] = byte 2
   // [C|C|D|D|D|D|D|D] = byte 3
   static unsigned char state = 0;

   TMR3CN &= 0x7F;                     // clear the T3 interrupt flag

   // check if the PLAY switch was pressed and playing should stop
   if (DAC_STOP_FLAG == 1)
   {
      TMR3CN = 0x00;                   // turn off T3
      DAC_STOP_FLAG = 0;               // reset the flag
      current_play_addr = 0x00000000;  // start at the beginning address
      predicted_value = mid_range;     // reset the predictor
      state = 0;                       // reset the playback state machine
   }
   else
   {
      // check for the end of the recording
      if (current_play_addr >= rec_end_addr)
      {
         TMR3CN = 0x00;                // turn off the timer
         REC_END_FLAG = 1;             // tell the T1 ISR to turn off the LED
         current_play_addr = 0x00000000;
         predicted_value = mid_range;  // reset the predictor
         state = 0;                    // reset the playback state machine
      }
      else
      {
         // unpack the DPCM code bytes retrieved from memory
         switch (state)
         {
             // state machine: 0 -> 1 -> 2 -> 3
             //                ^______________|
             case 0:

               packed_code = Read_MEM (current_play_addr);
               current_play_addr++;

               // take the DPCM code from the 6 high bits
               // [A|A|A|A|A|A| | ] = byte 1
               dpcm_code = (packed_code >> 2) & 0x3F;

               state = 1;
               break;

             case 1:

               // take the next DPCM code from the 2 low bits
               // of the previously retrieved byte
               // [-|-|-|-|-|-|B|B] = byte 1
               dpcm_code = (packed_code << 4) & 0x30;

               packed_code = Read_MEM (current_play_addr);
               current_play_addr++;

               // take the rest of the DPCM code from the
               // 4 high bits of the next retrieved byte
               // [B|B|B|B| | | | ] = byte 2

               dpcm_code |= (packed_code >> 4) & 0x0F;

               state = 2;
               break;

             case 2:

               // take the next DPCM code from the
               // 4 low bits of the previously retrieved byte
               // [-|-|-|-|C|C|C|C] = byte 2
               dpcm_code = (packed_code << 2) & 0x3C;

               packed_code = Read_MEM (current_play_addr);
               current_play_addr++;

               // take the rest of the DPCM code from the
               // 2 high bits of the next retrieved byte
               // [C|C| | | | | | ] = byte 3
               dpcm_code |= (packed_code >> 6) & 0x03;

               state = 3;
               break;

             case 3:

               // take the next DPCM code from the
               // 6 low bits of the previously retrieved byte
               // [-|-|D|D|D|D|D|D] = byte 3
               dpcm_code = packed_code & 0x3F;

               state = 0;
               break;

             default:
               state = 0;
               break;
         }

         // calculate the new predicted value
         predicted_value += DPCM_Decode (dpcm_code);

         // output the new sample to the speaker
         IDA0DAT = predicted_value;

         // overwrite the very last sample so the output is at the mid-range
         // when stopped
         // the discontinuity causes a small "clicking" sound when playback
         // starts and stops
         if (current_play_addr >= rec_end_addr)
         {
            IDA0DAT = mid_range;
         }
      }
   }
}

//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -