101 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			101 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "config.h"
 | 
						|
#include "timer.h"
 | 
						|
 | 
						|
/* Setup a 16-bit timer to overflow at the specified frequency
 | 
						|
     timer = 1-9
 | 
						|
     freq = Hz, or 0 to disable the timer.
 | 
						|
     interrupt = 1 to enable interrupt, 0 to disable
 | 
						|
*/
 | 
						|
int timer_setup_16bit(int timer, uint32_t freq, int ie)
 | 
						|
{
 | 
						|
        uint32_t period;
 | 
						|
        uint16_t prescale;
 | 
						|
 | 
						|
        if (timer < 1 || timer > 9)
 | 
						|
                return -1;
 | 
						|
 | 
						|
        if (freq == 0) {
 | 
						|
                switch(timer) {
 | 
						|
                case 1: T1CONbits.TON = 0; return 0;
 | 
						|
                case 2: T2CONbits.TON = 0; return 0;
 | 
						|
                case 3: T3CONbits.TON = 0; return 0;
 | 
						|
                case 4: T4CONbits.TON = 0; return 0;
 | 
						|
                case 5: T5CONbits.TON = 0; return 0;
 | 
						|
                case 6: T6CONbits.TON = 0; return 0;
 | 
						|
                case 7: T7CONbits.TON = 0; return 0;
 | 
						|
                case 8: T8CONbits.TON = 0; return 0;
 | 
						|
                case 9: T9CONbits.TON = 0; return 0;
 | 
						|
                }
 | 
						|
        }
 | 
						|
 | 
						|
        /* Figure out timer prescaler and period values.  Max period
 | 
						|
           is 65535 (PRx = 65534) so we can still attain 100% duty
 | 
						|
           cycle when using a timer for PWM. */
 | 
						|
        if ((period = FCY / (freq * 1L)) <= 65535)
 | 
						|
                prescale = 0;
 | 
						|
        else if ((period = FCY / (freq * 8L)) <= 65535)
 | 
						|
                prescale = 1;
 | 
						|
        else if ((period = FCY / (freq * 64L)) <= 65535)
 | 
						|
                prescale = 2;
 | 
						|
        else if ((period = FCY / (freq * 256L)) <= 65535)
 | 
						|
                prescale = 3;
 | 
						|
        else
 | 
						|
                prescale = 3, period = 65535;
 | 
						|
        if (period > 0)
 | 
						|
                period -= 1;
 | 
						|
 | 
						|
        switch (timer) {
 | 
						|
#define __timer_setup_case(x) \
 | 
						|
case x: \
 | 
						|
        T##x##CONbits.TON = 0; \
 | 
						|
        T##x##CONbits.TCKPS = prescale; \
 | 
						|
        PR##x = period; \
 | 
						|
        T##x##CONbits.TON = 1; \
 | 
						|
        break
 | 
						|
                __timer_setup_case(1);
 | 
						|
                __timer_setup_case(2);
 | 
						|
                __timer_setup_case(3);
 | 
						|
                __timer_setup_case(4);
 | 
						|
                __timer_setup_case(5);
 | 
						|
                __timer_setup_case(6);
 | 
						|
                __timer_setup_case(7);
 | 
						|
                __timer_setup_case(8);
 | 
						|
                __timer_setup_case(9);
 | 
						|
#undef __timer_setup_case
 | 
						|
        }
 | 
						|
 | 
						|
        /* Enable interrupt if requested */
 | 
						|
        timer_clear_txif(timer);
 | 
						|
        switch (timer) {
 | 
						|
        case 1: IEC0bits.T1IE = ie; break;
 | 
						|
        case 2: IEC0bits.T2IE = ie; break;
 | 
						|
        case 3: IEC0bits.T3IE = ie; break;
 | 
						|
        case 4: IEC1bits.T4IE = ie; break;
 | 
						|
        case 5: IEC1bits.T5IE = ie; break;
 | 
						|
        case 6: IEC2bits.T6IE = ie; break;
 | 
						|
        case 7: IEC3bits.T7IE = ie; break;
 | 
						|
        case 8: IEC3bits.T8IE = ie; break;
 | 
						|
        case 9: IEC3bits.T9IE = ie; break;
 | 
						|
        }
 | 
						|
 | 
						|
        return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* sleep for between "ms" and "ms+1" milliseconds */
 | 
						|
void msleep(int ms)
 | 
						|
{
 | 
						|
	static int initialized = 0;
 | 
						|
 | 
						|
	if (!initialized) {
 | 
						|
		timer_setup_16bit(1, 1000, 0);
 | 
						|
		initialized = 1;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Very basic, assumes timer1 is set up at 1 khz */
 | 
						|
	while (ms-- >= 0) {
 | 
						|
		IFS0bits.T1IF = 0;
 | 
						|
		while(IFS0bits.T1IF == 0)
 | 
						|
			continue;
 | 
						|
	}
 | 
						|
}
 |