/*
 * Atmel644_Bootloader.c
 *
 * Created: 19.12.2023 13:55:43
 * Author : eros.schatzmayer
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/boot.h>
#include <util/delay.h>
#include "DrvUart.h"

#define BOOT_UART_BAUD_RATE		UART_BAUD_SELECT(9600, 20000000UL)
#define XON						17		// XON Zeichen  --> Flusssteuerung
#define XOFF					19		// XOFF Zeichen --> Flusssteuerung


int main(void)
{
	unsigned int	c=0;		// Empfangenes Zeichen + Statuscode
	unsigned char	temp,		// Variable
					flag=1,		// Flag zum Steuern der Endlosschleife
					p_mode=0;	// Flag zum Steuern des Programmiermodus
    
	void (*start)( void ) = 0x0000;		// Funktionspointer auf 0x0000
	/* Definiert eine Funktion an der Stelle 0x0000. Beim Aufruf der Funktion start(); springt der Programmcounter
	   und damit das Programm an die Adresse 0x0000 und das Anwendungsprogramm kann starten.
	
	/* Interrupt Vektoren verbiegen */
	char sregtemp = SREG;
	cli();
	temp = MCUCR;
	MCUCR = temp | (1<<IVCE);
	MCUCR = temp | (1<<IVSEL);
	SREG = sregtemp;
	/* Da der Bootloadercode an einer bestimmten Adresse liegt (in diesem Fall 0x7000) muss die Sprungtabelle der
	   Interrupts entsprechend angepasst werden, um den AVR zu veranlassen, bei Auslösung eines Interrupts an die
	   Adresse 0x7000 + X zu springen und DANN zur ISR */
	
	/* Einstellen der Baudrate und Aktivieren der Interrupts */
	uart_init(BOOT_UART_BAUD_RATE);
	sei();
	
	uart_puts("Hallo hier ist der Bootloader\n\r");
	_delay_ms(1000);
	
	while (flag)
	{
		c = uart_getc();
		if ( !(c & UART_NO_DATA) )
		{
			switch((unsigned char)c)
			{
				case 'q':
					flag = 0;
					uart_puts("Verlasse den Bootloader!\n\r");
					break;
				default:
					uart_puts("Du hast folgendes Zeichen gesendet: ");
					uart_putc((unsigned char)c);
					uart_puts("\n\r");
					break;	
			}
		}
	} 
	
	uart_puts("Springe zur Adresse 0x0000!\n\r");
	_delay_ms(1000);
	
	/* vor Rücksprung eventuell benutzte Hardware deaktivieren
	   und Interrupts global deaktivieren, da kein echter Reset erfolgt */
	
	/* Interrupt Vektoren wieder gerade biegen */
	cli();
	temp = MCUCR;
	MCUCR = temp | (1<<IVCE);
	MCUCR = temp & ~(1<<IVSEL);
	
	/* Rücksprung zur Adresse 0x0000 */
	start();
	return 0;

}
