//////////////////////////////////////////////////////////////////////////////// /*! @file ClocksSimple.c Convinience functions for AT90USB162 timers/counters. - Part of the MSDN firmware. - Part of the Research Assistant project. - Copyright(C) 2014, Dmitry K. Nelson, St.Petersburg, Russia. D.Nelson@mail.ioffe.ru - Copyright(C) 2016, Viktor E. Bursian, St.Petersburg, Russia. Viktor.Bursian@mail.ioffe.ru */////////////////////////////////////////////////////////////////////////////// #include #include #include //------------------------------------------------------------------------------ #ifndef F_TIMER0 # ifndef F_CPU # error "Neither F_TIMER0 nor F_CPU are defined for ClocksSimple" # else # define F_TIMER0 F_CPU # endif #endif #ifndef F_TIMER1 # ifndef F_CPU # error "Neither F_TIMER1 nor F_CPU are defined for ClocksSimple" # else # define F_TIMER1 F_CPU # endif #endif int8_t Clock0_Signalled = 0; int8_t Clock1_Signalled = 0; //------------------------------------------------------------------------------ #if MCU == at90usb162 //------------------------------------------------------------------------------ const int8_t Clock_DividerLog [6] = // Divider | if F_CPU = 16 MHz // | TickFrequency | TickInterval { 32 // inf | 0 | inf (clock stopped) , 0 // 1 | 16 MHz | 1/16 us , 3 // 8 | 2 MHz | 1/2 us , 6 // 64 | 250 kHz | 4 us , 8 // 256 | 62500 Hz | 16 us , 10 // 1024 | 15625 Hz | 64 us }; //------------------------------------------------------------------------------ uint32_t Clock0_TickFrequency (void) { return ((uint32_t)F_TIMER0) >> Clock_DividerLog[ TCCR0B & 0b00000111 ]; } uint32_t Clock0_TickInterval (void) /*ns*/ { uint32_t TickFrequency = Clock0_TickFrequency(); if( TickFrequency ){ uint32_t TickInterval = 0x3B9ACA00; // =10^9 TickInterval /= TickFrequency; return TickInterval; }else{ return 0xFFFFFFFF; } } void Clock0_SetTickFrequency (uint32_t frequency/*Hz*/) { uint32_t CPUFrequency = F_TIMER0; uint8_t Mode; frequency <<= 1; for( Mode = 1 ; Mode < 6 ; Mode++ ){ if( frequency > ( CPUFrequency >> Clock_DividerLog[Mode] ) ) break; } if( Mode == 6 ) Mode = 0; TCCR0B = (TCCR0B & 0b11111000) | Mode; } uint32_t Clock0_Period (void) /*ns*/ { return Clock0_TickInterval() * ( (uint16_t)OCR0A + 1 ); } int8_t Clock0_SetPeriod (uint32_t period /*ns*/) { uint32_t TickFrequency = Clock0_TickFrequency(); if( TickFrequency ){ uint32_t PeriodInTicks = period / Clock0_TickInterval(); if( PeriodInTicks > 0xFF ){ OCR0A = 0xFF; //period = 0x100 ticks return 1; }else if( PeriodInTicks > 1 ){ OCR0A = (uint8_t)(PeriodInTicks-1); return 0; }else{ OCR0A = 0x00; //period = 1 tick return -1; } } return -2; } //------------------------------------------------------------------------------ uint32_t Clock1_TickFrequency (void) { return ((uint32_t)F_TIMER1) >> Clock_DividerLog[ TCCR1B & 0b00000111 ]; } uint32_t Clock1_TickInterval (void) /*ns*/ { uint32_t TickFrequency = Clock1_TickFrequency(); if( TickFrequency ){ uint32_t TickInterval = 0x3B9ACA00; // =10^9 TickInterval /= TickFrequency; return TickInterval; }else{ return 0xFFFFFFFF; } } void Clock1_SetTickFrequency (uint32_t frequency/*Hz*/) { uint32_t CPUFrequency = F_TIMER1; uint8_t Mode; frequency <<= 1; for( Mode = 1 ; Mode < 6 ; Mode++ ){ if( frequency > ( CPUFrequency >> Clock_DividerLog[Mode] ) ) break; } if( Mode == 6 ) Mode = 0; TCCR1B = (TCCR1B & 0b11111000) | Mode; } uint32_t Clock1_Period (void) /*ns*/ { return Clock1_TickInterval() * ( (uint32_t)((((uint16_t)OCR1AH) << 8) + OCR1AL) + 1 ); } int8_t Clock1_SetPeriod (uint32_t period /*ns*/) { uint32_t TickFrequency = Clock1_TickFrequency(); if( TickFrequency ){ uint32_t PeriodInTicks = period / Clock1_TickInterval(); if( PeriodInTicks > 0xFFFF ){ OCR1AH = 0xFF; OCR1AL = 0xFF; return 1; }else if( PeriodInTicks > 1 ){ OCR1AH = (uint8_t)(((PeriodInTicks-1) >> 8) & 0xFF); OCR1AL = (uint8_t)((PeriodInTicks-1) & 0xFF); return 0; }else{ OCR1AH = 0x00; OCR1AL = 0x00; return -1; } } return -2; } //------------------------------------------------------------------------------ #endif // MCU == at90usb162