All pastes #1897313 Raw Edit

Serial Driver - C-File

public c v1 · immutable
#1897313 ·published 2010-07-09 15:55 UTC
rendered paste body
#include "femtoos_code.h"#define abs(x) ((x)>0?(x):-(x))/** @ToDo: More flexible serialSendXXX methods, let the user choose the FIFO  *   * @ToDo: Serial driver configuration with config_application.h  *  * @ToDo: Rx  *  * @ToDo: Swap to an external file.    * @ToDo: The first serialSendXXX call will only print some rubbish.  *//** Initializes UART 0. This is copied from the arduio project (www.arduino.cc)  * It configures the baud rate and enables the Tx part of UART 0.  *  * @param uint16_t baud:  *     The desired baud rate. UART 0 will be configured to this baud rate.  *  * @ToDo: Think about it ;-)  */void serialInit(uint16_t baud){	uint8_t use_u2x;	uint16_t baud_setting;		// U2X mode is needed for baud rates higher than (CPU Hz / 16)	if(baud > (F_CPU / 16UL))	{		use_u2x = 1;	}	else	{		// figure out if U2X mode would allow for a better connection				// calculate the percent difference between the baud-rate specified and		// the real baud rate for both U2X and non-U2X mode (0-255 error percent)		uint8_t nonu2x_baud_error = abs((int)(255-((F_CPU/(16*(((F_CPU/8/baud-1)/2)+1))*255)/baud)));		uint8_t u2x_baud_error = abs((int)(255-((F_CPU/(8*(((F_CPU/4/baud-1)/2)+1))*255)/baud)));				// prefer non-U2X mode because it handles clock skew better		use_u2x = (nonu2x_baud_error > u2x_baud_error);	}	if(use_u2x)	{		UCSR0A = _BV(U2X0);		baud_setting = (F_CPU / 4UL / baud - 1UL) / 2UL;	}	else	{		UCSR0A = 0;		baud_setting = (F_CPU / 8UL / baud - 1UL) / 2UL;	}			// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)	UBRR0H = baud_setting >> 8;	UBRR0L = baud_setting;		UCSR0B = _BV(TXEN0) | _BV(UDRIE0);}/************************************** * Tels the SerialSend task that he can now write the next byte on the wire. */void USART0_UDRE_vect(void) __attribute__ ( ( signal, naked, used, externally_visible ) );void USART0_UDRE_vect(void){	/// @ToDo: Is there an faster alternative?	isrBegin();		// Tell the SerialSend task that it should look for free UARTs	isrFireEventOnName(QueuSendEvent);		// Disable this ISR, since this bit isn't cleard by hardware and we would be	// caught in endless ISR loop.	UCSR0B &= ~_BV(UDRIE0);		/// @ToDo: Is there an faster alternative?	isrEndYield();}/************************************** * Init everything. */void appBoot(void){	serialInit(9600UL);}/************************************** * Task reading UART Tx buffers and sending the data over the wire. */#if (preTaskDefined(SerialSend))void appLoop_SerialSend(void){	while (true)	{		// We check only whether the we can send something and won't block		// because there could be more than one send queu to check.		//		// If we can send, lock the queu.		//		// If you have more UARTs on the chip and want to use it, copy and adapt		// the following if block		if((UCSR0A & _BV(UDRE0)) && taskQueuReadRequestOnName(Uart0Buffer, 1, defLockDoNotBlock))		{			// Enable interrupts before we write the new byte to the wire.			// Otherwise this task could be interrupted and we will miss the			// event.			UCSR0B |= _BV(UDRIE0);						// Read the byte from the FIFO and write it to the wire.			UDR0 = genQueuReadOnName(Uart0Buffer);						taskQueuReleaseOnName(Uart0Buffer);		}				// Don't block for ever because we won't miss under any circumstances		// an free UART. So we check on a regular basis for ourselves whether		// the UART is free or not.		taskWaitForEventOnName(QueuSendEvent, 1000);	}}#endif/** Private implementation which sends a an uint16_t with the UART interface.  * You can change the type of the value parameter to an other integer type as  * required. You can also define a signed integer type. This version is  * inspired by Lukás Chmelas C++ itoa method in version 0.4.  *   * @param uint16_t value:  *     The intager value which should be send with the UART interface in a base  *     defined by the base parameter.  *   * @param int base:  *     Defines in which base the value parameter should be written to the UART  *     interface. The base has to be betwen and including 2 and 16.  *   * @param int newLine:  *     If set to 0, no new line ("\r\n") will be appended to the value.  *     Otherwise a new line will be appended  */void privSerialPrintInt(uint16_t value, int base, int newLine){	char result[10];	char* ptr = result;	char* ptr1 = result;	long int tmp_value;		do	{		tmp_value = value;		value /= base;		*ptr++ = "FEDCBA9876543210123456789ABCDEF" [15 + (tmp_value - value * base)];	} while(value);		// Apply negative sign	if(tmp_value < 0)	{		*ptr++ = '-';	}		if(taskQueuWriteRequestOnName(Uart0Buffer, ptr - ptr1 + (newLine != 0 ? 3 : 1), defLockBlockInfinite))	{		while(ptr1 < ptr)		{			genQueuWriteOnName(Uart0Buffer, *(--ptr));		}				if(newLine != 0)		{			genQueuWriteOnName(Uart0Buffer, '\r');			genQueuWriteOnName(Uart0Buffer, '\n');		}				taskQueuReleaseOnName(Uart0Buffer);		genFireEventOnName(QueuSendEvent);	}}#define serialPrintInt(value, base) privSerialPrintInt(value, base, 0)#define serialPrintIntLn(value, base) privSerialPrintInt(value, base, 1)/** Sends a single character with the UART interface.  *   * @param const char character:  *     The character which should be send.  */void serialPrintChar(const char character){	if(taskQueuWriteRequestOnName(Uart0Buffer, 1, defLockBlockInfinite))	{		genQueuWriteOnName(Uart0Buffer, character);		taskQueuReleaseOnName(Uart0Buffer);		genFireEventOnName(QueuSendEvent);	}}/** Sends a single character with the UART interface and appends a new line  * ("\r\n").  *   * @param const char character:  *     The character which should be send.  */void serialPrintCharLn(const char character){	if(taskQueuWriteRequestOnName(Uart0Buffer, 3, defLockBlockInfinite))	{		genQueuWriteOnName(Uart0Buffer, character);		genQueuWriteOnName(Uart0Buffer, '\r');		genQueuWriteOnName(Uart0Buffer, '\n');		taskQueuReleaseOnName(Uart0Buffer);		genFireEventOnName(QueuSendEvent);	}}/** Sends text, terminated by an '\0' character, with the UART interface.  *   * @param const char text[]:  *     The '\0' character terminated text which should be send.  */void serialPrintText(const char text[]){	if(taskQueuWriteRequestOnName(Uart0Buffer, strlen(text), defLockBlockInfinite))	{		while(*text)		{			genQueuWriteOnName(Uart0Buffer, *text++);		}		taskQueuReleaseOnName(Uart0Buffer);		genFireEventOnName(QueuSendEvent);	}}/** Sends text, terminated by an '\0' character, with the UART interface and  * appends a new line ("\r\n").  *   * @param const char text[]:  *     The '\0' character terminated text which should be send.  */void serialPrintTextLn(const char text[]){	if(taskQueuWriteRequestOnName(Uart0Buffer, strlen(text) + 2, defLockBlockInfinite))	{		while(*text)		{			genQueuWriteOnName(Uart0Buffer, *text++);		}		genQueuWriteOnName(Uart0Buffer, '\r');		genQueuWriteOnName(Uart0Buffer, '\n');		taskQueuReleaseOnName(Uart0Buffer);		genFireEventOnName(QueuSendEvent);	}}/************************************** * Task that tries to write much as possible into the queu. */#if (preTaskDefined(Main))void appLoop_Main(void){	while (true)	{		serialPrintText("Current ");		serialPrintTextLn("status");		serialPrintChar('O');		serialPrintCharLn('K');		serialPrintInt(13, 10);		serialPrintIntLn(55, 16);				taskDelayFromNow(4000);	}}#endif