#include "stm32f10x.h"
#include "type.h"
#include "core_cm3.h"
#include "global.h"
#include "freeruntimer.h"

void init_SWO(void);
void SWO_write_byte(uint8 byte);

int main(void)
{
	////
	init_SWO();

	////
	FreerunTimerInit();

	RCC->APB2ENR |= (1<<3) | (1<<0);				// Enable the GPIOB
	AFIO->MAPR &= ~(0x07<<24);

	while(1)
	{
		////
		timer_delay(ms_ToTimerTicks(1000));

		////
		SWO_write_byte(0x55);
		SWO_write_byte(0x44);
		SWO_write_byte(0x33);
		SWO_write_byte(0x22);
		SWO_write_byte(0x11);
	}
}

///////////////////////////////////////////////////////////////////////////////////////////
#define DEMCR	*((volatile uint32 *) 0xE000EDFC)
#define DBGMCU_CR	*((volatile uint32 *) 0xE0042004)

void init_SWO(void) {
		uint32 SWOSpeed = 19200;	// bps
		uint32 SWOPrescaler = (24000000 / SWOSpeed) - 1; // SWOSpeed in Hz
		DEMCR = 1<<24;			// TRCENA
		DBGMCU_CR = 0x00000027; //Enabling TRACE_IOEN, DBG_STANDBY, DBG_STOP, DBG_SLEEP
		*((volatile unsigned *) 0xE00400F0) = 0x00000002; // "Selected PIN Protocol Register": Select which protocol to use for trace output (2: SWO)
		*((volatile unsigned *) 0xE0040010) = SWOPrescaler; // "Async Clock Prescaler Register". Scale the baud rate of the asynchronous output
		*((volatile unsigned *) 0xE0000FB0) = 0xC5ACCE55; // ITM Lock Access Register, C5ACCE55 enables more write access to Control Register 0xE00 :: 0xFFC
		*((volatile unsigned *) 0xE0000E80) = 0x0001000D; // ITM Trace Control Register
		*((volatile unsigned *) 0xE0000E40) = 0x0000000F; // ITM Trace Privilege Register
		*((volatile unsigned *) 0xE0000E00) = 0x00000001; // ITM Trace Enable Register. Enabled tracing on stimulus ports. One bit per stimulus port.
		*((volatile unsigned *) 0xE0001000) = 0x400003FE; // DWT_CTRL
		*((volatile unsigned *) 0xE0040304) = 0x00000100; // Formatter and Flush Control Register
}

///////////////////////////////////////////////////////////////////////////////////////////
void SWO_write_byte(uint8 byte)
{
	if(DEMCR & (1ul<<24)) // Trace enabled
	{
		if(ITM->TCR & ITM_TCR_ITMENA_Msk) // ITM enabled
		{
			if(ITM->TER & (1ul << 0)) // ITM Port #0 enabled
			{
				while(0 == ITM->PORT[0].u32);
				ITM->PORT[0].u16 = 0x08 | (byte<<8);
			}
		}
	}
}

///////////////////////////////////////////////////////////////////////////////////////////