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

📄 mp3menus.c

📁 Frank s MP3 Player Source Files
💻 C
📖 第 1 页 / 共 4 页
字号:
                PositionLCDcursor(4, 1);
                uart1_putwaitPROGstr((u08*)pgm_read_word(FnArrayPtr+IRFuncString));             
                break;

            case BUT_DOWN:
                ButtonPress = 0;                    // clear out the button press so we don't do this again
                // clear out the old menu name on the LCD display
                ClearLCDlines(4, 2);
                // Point to next menu record (ie next in the linked list)            
                FnArrayPtr = (PGM_VOID_P)pgm_read_word(FnArrayPtr+IRNextFunc);
                // Display the name of our new menu item (first move cursor to start of 4th line)
                PositionLCDcursor(4, 1);
                uart1_putwaitPROGstr((u08*)pgm_read_word(FnArrayPtr+IRFuncString));             
                break;
            }
        }
        
        // If we're here it's because the MENUSEL button was pressed, exiting us from the above switch statement,
        // because the user selected a player function (play, stop, next, etc) so learn the IR code for that . 
        // Then wrap-up & return to the player.
        ButtonPress  = 0;                                           // clear out the button press that got us here 
        ClearLCDlines(1, 8);                                        // blank all the LCD display lines 
    	PositionLCDcursor(1, 1);	
        uart1_putwaitPROGstr(PSTR("Hold remote control     30 cm from MP3 player   IR reciever then press  remote control button."));

        TrainIRfunction(pgm_read_word(FnArrayPtr+IRFuncEEPROM));    // learn IR code, passing in eeprom location to store results

        // Now ask the user if they want to train again
        ClearLCDlines(1, 8);                                        // blank all the LCD display lines 
    	PositionLCDcursor(1, 1);	
        uart1_putwaitPROGstr(PSTR("IR code received."));
    	PositionLCDcursor(3, 1);	
        uart1_putwaitPROGstr(PSTR("Do you wish to train    another function?"));
    	PositionLCDcursor(6, 1);	
        uart1_putwaitPROGstr(PSTR("Select=yes,  others=no"));
        ButtonPress = 0;
        while (!ButtonPress);                                       // wait until a button is pressed
        if (ButtonPress != BUT_MENUSEL)
            trainon = 0;                                            // clear flag if Select not pressed
        ButtonPress = 0;                                            // clear out the button press
        ClearLCDlines(1, 8);                                        // blank all the LCD display lines 
    }                                                               // bottom of "do you want to train another?" loop
}





// TrainIRfunction
//
// This is the routine that does the "heavy lifting" for IR remote control learning. It
// receives the IR code bit sequence, analyses it, and then stores the result in the eeprom, 
// at the passed-in eeprom address. It MUST receive an IR signal; it'll wait here forever 
// if it doesn't see one.
void TrainIRfunction (u16 eepromaddr)
{
    u08     starttime;
    u16     *buffpointer;
    u16     periodcount, i, j, sum, lowbar, highbar, T;

    T = 0;

    // disable input capture 3 interrupt; we want to poll the captures in this routine
    // ensure other capture parameters set up correctly. With prescaler set to /256, each increment
    // of TCNT3 takes 16 us. 
    *AVR_ETIMSK = *AVR_ETIMSK & 0xdf;           // disable input capture 3 interrupt
    *AVR_TCCR3B = 0x84;                         // prescaler = /256, noise canceller ON, capture on falling edge
    *AVR_ETIFR  = *AVR_ETIFR | 0x20;            // ensure capture3 interrupt flag clear
    // init location to put periods data
    buffpointer = (u16*)&MP3DATAQ[10];          // point into MP3 data Q. Partway in to avoid changing the Q headers.

    // Now sit back & wait for the start of the IR signal (a falling edge). When it arrives, clear the
    // counter, kick off the timeout, and start recording periods. Wait until bit 5 (ICF3 flag) in ETIFR
    // register is set; when set this indicates a capture has occurred.
    while (!(*AVR_ETIFR & 0x20));

    // Capture has occurred - falling edge detected. An IR signal has begun. Start recording periods. 
	// Record periods until either we get 200 of them, or 200 ms has passed.
    *AVR_TCNT3H = 0;
    *AVR_TCNT3L = 0;                            // zero the counter register; ready for next period measurement
    *AVR_TCCR3B = *AVR_TCCR3B ^ 0x40;           // tell AVR to do next capture on the other edge (rising edge)
    *AVR_ETIFR  = 0x20;                         // clear ICF3 interrupt flag so we can detect next capture
    starttime = Tick100ms;                      // start timeout
    periodcount = 0;

    while ((Tick100ms-starttime)<2) {
        while (!(*AVR_ETIFR & 0x20));           // wait for input capture to occur
        *AVR_TCNT3H = 0;
        *AVR_TCNT3L = 0;                        // zero the counter register; ready for next period measurement
        *AVR_TCCR3B = *AVR_TCCR3B ^ 0x40;       // tell AVR to do next capture on the other edge (opposite edge)
        *buffpointer++ = *AVR_ICR3L + ((*AVR_ICR3H)<<8);      // store timeperiod
        periodcount++;
        if (periodcount>200) break;
        *AVR_ETIFR  = 0x20;                     // clear ICF3 interrupt flag so we can detect next capture  
    }                                           // end while loop
    // execute here when we've timed out - we've now captured all the IR period data we're going to

    if (periodcount < 10) goto WrapUp;          // exit if too short a received code (array of periods)

	// Now we go through a bunch of work to determine an estimate for "T", the bit period. The sole point of
	// this exercise is that knowing the bit period is very useful for determining when one sequence of IR periods
	// has finished and a new one has begun. Remote controls transmit continuously while you're holding a button
	// down; they will retransmit the IR sequence over and over until you release their button, each IR sequence
	// separated by a gap. That gap is easiest to detect if you know the bit period.

    // Determine initial value for "T", the bit period, by finding the second-smallest period in the array
    // of periods, excluding the first 2 and last 2 periods (header & trailer). 
    buffpointer = (u16*)&MP3DATAQ[10];
    buffpointer++;
    buffpointer++;                              // skip over the first 2 periods in the array    
    j=*buffpointer++;                           // (initial value for...) j is smallest period
    T=j;                                        // (initial value for...) T is second-smallest period
    i = periodcount - 5;                        // this is how many periods we want to check (not 1st & last 2, & we just did one)    
    do {
        if (*buffpointer < j) {                 // if we've found a new smallest-period value...
            T = j;                              //   then previous smallest-period is now the second-smallest period
            j = *buffpointer;                   //   and record new smallest-period value
        }
        buffpointer++;                          // move on to next period entry        
    } while (i--);                              // repeat until all periods have been checked

    // At this point T contains our initial period estimate, being the second-smallest period value found in
    // the bulk of the periods array. Now we want to refine that T estimate. We do that by trying to find the
    // first eight periods in the bulk of the array of approximate length T, summing them and dividing by 8.
    // To get a new, much more accurate, value of T. "Approximate value of T" is defined as the period value
    // being within 1/2T  (ie 0.5T to 1.5T is acceptable as being a T).
    buffpointer = (u16*)&MP3DATAQ[10];
    buffpointer++;
    buffpointer++;                              // skip over the first 2 periods in the array 
    sum = 0;                                    // this is the sum of the (hopefully 8) T's
    j = 0;                                      // how many T's we've found
    lowbar  = T>>1;                             // low acceptable threshold value for T  (0.5*T)
    highbar = T + lowbar;                       // high acceptable threshold value for T
    i = periodcount - 4;                        // this is how many periods we want to check (not 1st & last 2)
    while (i-- && (j<8)) {
        if ( (*buffpointer>lowbar) && (*buffpointer<highbar) ) {    // if current period is valid as a T then...
            sum += *buffpointer;                                    //  add it to the sum
            j++;                                                    //  and increment our T's count
        }
        buffpointer++;                                              // point to next period in the array
    }
    // Now do the division. New T value is sum / j.
    if (j)                                                          // if (j) avoids divide-by-error possibility
        T = DivRound (sum, j);                                      // integer division with rounding
    // At this point we have a new, fairly well refined, value for T - the received IR datastream bit period.
	
	
	// Now let's find out how many periods are actually in the IR sequence. We've captured "periodcount" number
	// of periods, including the first two which are the header periods (long periods, used for locking the PLL
	// in the IR detectors). Beyond the header periods, we're going to look for a period of duration greater than
	// 15 "T"s, ie greater than 15 bit periods. This will indicate the gap between repeating IR sequences.
	// Finally, note that we cannot store more than 63 periods in the eeprom, so if we find the sequence is longer
	// than 63 periods, we set it to 63. Store the result in j.
	buffpointer = (u16*)&MP3DATAQ[10];								// point to start of raw periods data
	buffpointer++;
	buffpointer++;													// skip past the two header periods
	j = 2;															// we still need to count them though
	i = periodcount-2;												// how many remaining periods to check
	// check each period's length in "T"s; break out of while loop if length exceeds 15 T's
	while ( (i--) && (DivRound(*buffpointer++, T)<16) ) {
		 j++;
	}
	if (j>63)  j=63;


    // DEBUG - print the periods raw data to the debug RS232 port
    if (IRtrain_debug) {
        uart0_putwaitPROGstr(PSTR("\r\nStart of IR period raw data\r\n"));
        uart0_putwaitPROGstr(PSTR("Number of raw periods: "));
        PrintASCIIword (periodcount, 0);
        uart0_putwaitPROGstr(PSTR("\r\nValue of T (bit period): "));
        PrintASCIIword (T, 0);
        uart0_putwaitPROGstr(PSTR("\r\nNumber of periods in IR sequence: "));
        PrintASCIIword (j, 0);
        uart0_putwaitPROGstr(PSTR("\r\n"));
		buffpointer = (u16*)&MP3DATAQ[10];           // point to start of periods data
        i = periodcount;
        while (i--) {
           PrintASCIIword (*buffpointer++, 0);
           uart0_putwaitPROGstr(PSTR("\r\n"));
        }
        uart0_putwaitPROGstr(PSTR("End of IR period raw data\r\n"));
    }
    // End DEBUG code section


    // Store the resultant array of periods in the eeprom. Including the length (number of periods, ie "j").
    // There are "j" number of periods of interest in the array, which we want to store into the eeprom.
	EEPROM_Write(eepromaddr++, (u08)j);         // write the number of periods into the eeprom (length byte)
    eepromaddr++;                               // skip over "buttonpress" value in eeprom; point to start of periods eeprom space
    buffpointer = (u16*)&MP3DATAQ[10];          // point to start of periods data
    while (j--) {
        EEPROM_Write(eepromaddr++, (u08)*buffpointer);    		// write low byte of period value into eeprom
		EEPROM_Write(eepromaddr++, (u08)(*buffpointer++>>8));   // write high byte of period value into eeprom
    }

    // all done; re-enable input capture 3 interrupts for normal IR receiver operation. Fix MP3 data Q.
    // Clear the IR decoder count bytes.
    WrapUp:

    // Zero the IR decoder sequence count values. So that the IR decoder (the regular decoder, not this special
	// training one) is starting from the beginning when attempting the decode a received sequence.
    i = IR_numcodes;
    while (i--)
        IRdecode_cnt[i] = 0;

    Q_clear_C((u08*)&MP3DATAQ[0]);              // ensure MP3 data Q empty (note we didn't overwrite the Q headers)  
    *AVR_TCCR3B = 0x84;                         // prescaler = /256, noise canceller ON, capture on falling edge
    *AVR_ETIMSK = *AVR_ETIMSK | 0x20;           // enable input capture 3 interrupt
}

⌨️ 快捷键说明

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