/*
* geigerzaehler . c
*
* Created : 28.02 .2019 09 : 07 : 22
* Author : John Ditgens , Alexander Brandscheidt
* Git - Repository : https : //gitea.Railduction.eu/JohnD/Geigerzaehler.git
*
* MController : AtMega328P
* Board : Arduino Nano
*/
# define F_CPU 16000000UL // Clock speed: 16 MHz - Speed from onboard oscillator
// Imports
# include <avr/io.h>
# include <avr/interrupt.h>
# include <stdint.h>
/*
* Global variable declaration
*/
// Set frequencys and general stuff
uint16_t boost_frequency = 2000 ; // 2kHz frequency
uint16_t signalOutput_piezo_time = 200 ; // 200ms
uint16_t signalOutput_led_time = 200 ; // 200ms
// Used for execution-timing (with timer) [0 = disabled, >0 = nextTimerTick] (1 is next avaible execution)
uint16_t boost_highVoltage_nextTick = 1 ; // Execute at start
uint16_t signalOutput_piezo_nextTick = 0 ;
uint16_t signalOutput_led_nextTick = 0 ;
// Prescaling of timer [timer-speed: cpu-clock / prescaler]
// Modes: [1, 8, 64, 256, 1024]
uint8_t timer1_prescaler = 256 ;
uint16_t timer1_overflow_value = ( 2 ^ 16 ) - 1 ; // Just for info
int main ( )
{
/*
* Init
*/
// Inputs
DDRD & = ( 0 < < PORTD2 ) ; // Activate input PD2
DDRD & = ( 0 < < PORTD3 ) ; // Activate input PD3
// Outputs
DDRD | = ( 1 < < PORTD4 ) ;
DDRD | = ( 1 < < PORTD5 ) ;
DDRD | = ( 1 < < PORTD6 ) ;
DDRB | = ( 1 < < PORTB5 ) ; // Onboard-Led
// Interrupts
// for INT0 Pin-D2 High-voltage check
EICRA | = ( 0 < < ISC01 ) | ( 1 < < ISC00 ) ; // On at any edge [Code: 01]
EIMSK | = ( 1 < < INT0 ) ; // Activate Interrupt INT0
// for INT1 Pin-D3 Counter-click
EICRA | = ( 1 < < ISC11 ) | ( 1 < < ISC10 ) ; // On rising edge [Code: 11]
EIMSK | = ( 1 < < INT1 ) ; // Activate Interrupt INT1
// Init timer1
timer1_init ( ) ;
// Endless loop
while ( 1 )
{
cli ( ) ; // Deactivate global interrupts (before checks)
/*
* HighVoltage boosting
*/
if ( boost_highVoltage_nextTick > 0 ) // If there is a nextTick
{
if ( ( uint16_t ) TCNT1 > = boost_highVoltage_nextTick & & ( ( uint16_t ) TCNT1 - boost_highVoltage_nextTick ) < ( timer1_overflow_value / 2 ) ) // If we are on or after the tick it should be executed
{
// Flip pin state
PORTD ^ = ( 1 < < PORTD4 ) ;
// Calculate when next high/low should be set
boost_highVoltage_nextTick = ( uint16_t ) TCNT1 + F_CPU / timer1_prescaler * 1 / ( boost_frequency / 2 ) ; // Half of time it should be high/low
if ( boost_highVoltage_nextTick = = 0 ) boost_highVoltage_nextTick + + ; // If its 0, it stops, we dont want that
}
}
/*
* Signal output
*/
// Piezo
if ( signalOutput_piezo_nextTick > 0 ) // If there is a nextTick
{
if ( ( uint16_t ) TCNT1 > = signalOutput_piezo_nextTick & & ( ( uint16_t ) TCNT1 - signalOutput_piezo_nextTick ) < ( timer1_overflow_value / 2 ) ) // If we are on or after the tick it should be executed
{
// Flip pin state
PORTD ^ = ( 1 < < PORTD5 ) ;
if ( ! ( PIND & ( 1 < < PORTD5 ) ) )
{
// We are on low (again), disable further execution
signalOutput_piezo_nextTick = 0 ;
}
// When the signal should next flip
signalOutput_piezo_nextTick = ( uint16_t ) TCNT1 + F_CPU / timer1_prescaler * signalOutput_piezo_time / 1000 ; // Calculate nextTick based on time in ms
if ( signalOutput_piezo_nextTick = = 0 ) signalOutput_piezo_nextTick + + ; // If its 0, it stops, we dont want that
}
}
// LED
if ( signalOutput_led_nextTick > 0 ) // If there is a nextTick
{
if ( ( uint16_t ) TCNT1 > = signalOutput_led_nextTick & & ( ( uint16_t ) TCNT1 - signalOutput_led_nextTick ) < ( timer1_overflow_value / 2 ) ) // If we are on or after the tick it should be executed
{
// Flip pin state
PORTD ^ = ( 1 < < PORTD6 ) ;
if ( ! ( PIND & ( 1 < < PORTD6 ) ) )
{
// We are on low (again), disable further execution
signalOutput_led_nextTick = 0 ;
}
// When the signal should next flip
signalOutput_led_nextTick = ( uint16_t ) TCNT1 + F_CPU / timer1_prescaler * signalOutput_led_time / 1000 ; // Calculate nextTick based on time in ms
if ( signalOutput_led_nextTick = = 0 ) signalOutput_led_nextTick + + ; // If its 0, it stops, we dont want that
}
}
}
sei ( ) ; // Activate global interrupts (after checks) [when an interrupt was fired, it will now be executed]
}
/*
* Init timer1 ( 16 - bit ) in " normal mode "
*/
void timer1_init ( )
{
// set up timer with speed: cpu-clock / prescaler
switch ( timer1_prescaler ) { // [CS12 CS11 CS10]
default :
case 1 :
TCCR1B | = ( 1 < < CS10 ) ; // [0 0 1 ]
break ;
case 8 :
TCCR1B | = ( 1 < < CS11 ) ; // [0 1 0 ]
break ;
case 64 :
TCCR1B | = ( 1 < < CS10 ) ; // [0 1 1 ]
TCCR1B | = ( 1 < < CS11 ) ;
break ;
case 256 :
TCCR1B | = ( 1 < < CS12 ) ; // [1 0 0 ]
break ;
case 1024 :
TCCR1B | = ( 1 < < CS10 ) ; // [1 0 1 ]
TCCR1B | = ( 1 < < CS12 ) ;
break ;
}
// initialize counter
TCNT1 = ( uint16_t ) 0 ;
}
/*
* ISR - Interrupt service routine
*/
// Address: 0x001 INT0 - On any edge [Code: 01]
// Handles: Over/Below working voltage
ISR ( INT0_vect )
{
if ( ! ( PIND & ( 1 < < PORTD2 ) ) ) // Falling edge
{
// Below ~400V, activate booster
boost_highVoltage_nextTick = 1 ; // Run as soon as possible
PORTB | = ( 1 < < PORTB5 ) ; // Onboard-Led
}
else // Rising edge
{
// Reached ~400V, deactivate booster
boost_highVoltage_nextTick = 0 ;
PORTB | = ( 0 < < PORTB5 ) ; // Onboard-Led
// reset state
PORTD | = ( 0 < < PORTD4 ) ; // pin on low
boost_highVoltage_nextHigh = 1 ; // next is high
}
reti ( ) ; // Exit interrupt-handler
}
// Address: 0x002 INT1 - On rising edge [Code: 11]
// Handles: Counter tube "tick"
ISR ( INT1_vect )
{
// Tick detected, signalOutput
signalOutput_nextTick = 1 ; // Run as soon as possible
reti ( ) ; // Exit interrupt-handler
}