/*
 * Copyright 2015 Mario Richter, Peter Stephan
 * This file is part of NeMo.
 *
 * NeMo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * NeMo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with NeMo.  If not, see <http://www.gnu.org/licenses/>.
 */


/*! 
 *  \mainpage Net-IO Projekt
 * Das Net-IO-Projekt soll ein universelles Netzwerk-Interface zum Ziel haben, mit dem
 * verschiedene Applikationen über eine Ethernet-Schnittstelle gesteuert werden können.
 * Hierbei ist hauptsächlich ein proprietäres TCP/IP-Protokoll vorgesehen, jedoch soll
 * auch die Möglichkeit bestehen, es durch weitere Protokollschichten zu erweitern
 * (z.B. Mailserver, Webserver, UDP ...). \n\n  
 * Als Controller kommt ein ATmega1281 zum Einsatz.
 *  \author Mario Richter
 *  \author Peter Stephan
 *  \version 0.1
 *  \date 2013-2015
 */

/*!
 * \file main.c
 * \ingroup	system
 * \brief	Haupt-Quellfile mit Main-, Init- und Interrupt-Funktionen.
 */

/*!
 * \defgroup system Systemfunktionen und Interrupts 
 */

#include "main.h"

volatile uint16_t   counter;
volatile uint8_t    timeflags;
volatile uint16_t   debugLevel;


/* ------------------------------------------------------------------------------------ */
/*!
 * \ingroup system
 * \brief Main-Funktion und Einsprungpunkt beim Programmstart.
 * 
 * Die Funktion dient zur Initialisierung des Controllers und der angeschlossenen Peripherie.
 * Außerdem enthält sie die main loop, in der niederpriore Aufgaben erledigt werden.
 */

int main(void)
{
	uint8_t i = 0;

  debugLevel = DEBUGLVL_DEFAULT;				      // Mit Default-Debuglevel beginnen
	
	DDRA = 0x0F;                                // Ausgänge für LEDs (PA0..3), Eingänge für Taster (PA5..7)
	PORTA = 0xEF;                               // LED-Ausgänge high (LEDs aus), Pullups für Taster aktivieren

	TCCR0A = (1 << WGM01);
	TCCR0B = (3 << CS00);									      // Timer0: 1ms-Interrupt, 64x Prescaler, CTC Mode
	OCR0A = 249;											          // 16MHz / 64 / 1kHz = 250; -1 da bei 0 begonnen wird
	TIMSK0 = (1 << OCIE0A);									    // Compare Match Interrupt freigeben

	i2cInit();                                  // I2C initialisieren
	usart_init();									              // USART initialisieren
	adcInit();                                  // ADC initialisieren

	enc28Init();										            // ENC28J60 initialisieren
	ipInitStack();										          // Netzwerkstack initialisieren
	lightInit();                                // Lichtsteuerung initialisieren

	for(i = 0; i < TCP_MAX_CONNECTIONS; i++)
	{
	  tcpConnList[i].status = TCP_STAT_CLOSED;
	}

	tcpListen(1396, (void *)tcpCmdHandler);			// Port öffnen, Handlerfunktion für TCP-Kommandos (NeMo zu NeMo)
	tcpListen(1397, (void *)tcpCmdHandler);			// Port öffnen, Handlerfunktion für TCP-Kommandos (PC zu NeMo)
	tcpListen(80,   (void *)httpHandler); 			// Port für Webserver öffnen, Handlerfunktion deklarieren

	ETH_INTERRUPT_ENABLE();										  // Externen Interrupt für ENC28J60 aktivieren */
	sei();												              // Interrupts global aktivieren
	
	while(1)
	{
	  ipHandlePacket();										      // Packet Handler für neu eingetroffene Packets*/
		usart_scheduler();										    // Scheduler für USART-Kommunikation
		usartCmdHandler();										    // Befehlshandler für USART-Befehle
		adcScheduler();                           // Scheduler für AD-Wandler

		if(timeflags & TIMEFLAG_10MS)							// **** 10ms-Routine ****
		{
		  timeflags &= ~TIMEFLAG_10MS;
		  tastAuswertung();
		  ledAusgabe();
		  tcpTimer();
		  httpTimer();
		  lightScheduler();
		}

		if(timeflags & TIMEFLAG_1S)								// **** 1s-Routine ****
		{
			timeflags &= ~TIMEFLAG_1S;
			adcStartCycle();                        // Neuen AD-Wandlerzyklus starten
			arpTimer();											        // ARP-Timer-Prozedur (Lebensdauer der Einträge)
		}
	}
}


/*!
 * \ingroup system
 * \brief USART-Empfangsinterrupt.
 * 
 * Diese Interruptfunktion wird vom Controller angesprungen, wenn ein neues Zeichen auf der
 * USART-Schnittstelle empfangen wurde. Sie ruft die Funktion \ref usart_new_char zur Behandlung
 * des neuen Zeichens auf.
 */

ISR(USART0_RX_vect)
{
	usart_new_char();
}


/*!
 * \ingroup system
 * \brief Timer0-Interrupt (1ms).
 * 
 * Diese Timer-Interruptfunktion wird vom Controller angesprungen, wenn 1ms vergangen ist. Sie dient
 * zum Timing zeitkritischer Funktionen und bildet die Zeitbasis des Systems.
 */

ISR(TIMER0_COMPA_vect)
{
	// Counter für Sequence-Nummern neuer TCP-Verbindungen hochzählen
	tcpInitialSeqCnt++;

	counter++;
	if((counter % 10) == 0)
	{
	  timeflags |= TIMEFLAG_10MS;
	}
	if((counter % 100) == 0)
	{
		timeflags |= TIMEFLAG_100MS;
	}
	if(counter >= 1000)
	{
		timeflags |= TIMEFLAG_1S;
		counter = 0;
	}
	
}


/*!
 * \ingroup system
 * \brief INT7-Interrupt (vom ENC28J60).
 * 
 * Dieser externe Interrupt wird vom ENC28J60 ausgelöst, wenn ein neues Packet eingetroffen ist.
 * Im Interrupt wird das Vorhandensein eines neuen Datenpaketes signalisiert, das dann in der main
 * loop abgeholt und verarbeitet wird.
 */
 
ISR(INT7_vect)
{
	newPacketPresent = 1;
	ETH_INTERRUPT_DISABLE();
}


