/* BlueDataDistributor - data distribution module from ethernet to 32 serial ports
 * version 0.1.1 date 2006-10-07
 * Copyright (C) 2006 Stefan Schuermans <stefan@blinkenarea.org>
 * a BlinkenArea project - http://www.blinkenarea.org/
 */

#include <avr/interrupt.h>
#include <avr/signal.h>

#include "arp.h"
#include "ip.h"
#include "random.h"
#include "rtl8019.h"
#include "serial.h"
#include "status.h"
#include "tcp.h"
#include "timing.h"
#include "udp.h"

// 208us tick counter to generate 20ms ticks
// 208us -> 4800bps (4808bps) (speed of serial outputs)
volatile unsigned char Timing208_96 = 0;

// flag set every 20ms to indicate execution of 20ms ticks
volatile unsigned char Timing20Flag = 0;

// wrapping around 20ms tick counter
unsigned char Timing20 = 0;

// 20ms tick counter to generate 200ms ticks
unsigned char Timing20_10 = 0;

// 208us interrupt (timer 0 compare match)
SIGNAL( SIG_OUTPUT_COMPARE0 )
{
  // call serial output
  SerialOutputBitTime( );
  // set flag every 20ms
  Timing208_96++;
  if( Timing208_96 >= 96 )
  {
    Timing208_96 = 0;
    Timing20Flag = 1;
  }
}

// initialize
void TimingInit( void ) // (extern)
{
  // configure timer 0 to 208us interval
  TCCR0 = 0<<FOC0 | 1<<WGM01 | 0<<WGM00 | // count to OCR0
          0<<COM01 | 0<<COM00 | // no waveform generation
          1<<CS02 | 1<<CS01 | 0<<CS00; // 1/256 of sysclock (16MHz) -> increment every 16us
  OCR0 = 12; // count to 12 -> 208us interval

  // enable timer 0 compare match interrupt
  TIMSK |= 1<<OCIE0;

  // configure timer 1 to count cycles
  TCCR1A = 0<<WGM11 | 0<<WGM10; // normal mode
  TCCR1B = 0<<WGM13 | 0<<WGM12 | 0<<CS12 | 0<<CS11 | 1<<CS10; // normal mode, no prescaler
}

// provide curent time stamp as entropy to random number generator
void TimingEntropy( void ) // (extern)
{
  unsigned short timestamp = TCNT1;
  RandomProvideEntropy( (unsigned char)timestamp );
  RandomProvideEntropy( (unsigned char)(timestamp >> 8) );
}

// provide curent 20ms tick counter as entropy to random number generator
void Timing20Entropy( void ) // (extern)
{
  RandomProvideEntropy( Timing20 );
}

// task function to do the work - call from main loop
void TimingTask( void ) // (extern)
{
  // 20ms not elapsed
  if( ! Timing20Flag )
    return;
  Timing20Flag = 0;

  // call 20ms tick functions

  // generate 200ms steps
  Timing20_10++;
  if( Timing20_10 >= 10 )
    Timing20_10 = 0;

  // call 200ms tick functions at different times
  switch( Timing20_10 )
  {
    case 1: ArpTick200( ); break;
    case 3: IpTick200( ); break;
    case 5: RtlTick200( ); break;
    case 6: StatusTick200( ); break;
    case 7: TcpTick200( ); break;
    case 9: UdpTick200( ); break;
  }
}

