EmbeddedRelated.com
The 2024 Embedded Online Conference

Binary Coded Decimal (BCD) - ASCII Converter

Dr Cagri Tanriover February 12, 2013 Coded in C
char bcdToAscii( unsigned char bcdNibble )
{
  char result;
	
  if( bcdNibble < 10 )
  {// valid BCD input. ( [0,9] is the valid range for BCD input. )
    result = (char)( bcdNibble + 48 );	// +48 is applicable to [0,9] input range.
  }// end if
  else
  {// invalid input
    result = '0';
  }// end else

  return( result );
	
}// end bcdToAscii()

unsigned char asciiToBcd( char asciiByte )
{/* Converts an input ASCII character (expected within the [ '0' - '9' ] range) into its BCD counterpart. */
	
  unsigned char result;

  if( 
      asciiByte >= '0'
      && asciiByte <= '9'
  )
  {// range check passed.
    result = (unsigned char)(asciiByte - 48);	// -48 offset gives the decimal value of the ASCII character.
  }
  else
  {// range check failed.
    result = 0;
  }// end else

  return( result );
	
}// end asciiToBcd()

Embedded Linux Frequency Meter

Fabiano Ferronato February 5, 2013 Coded in C for the TI OMAP 5912
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/arch/gpio.h>
#include <asm/arch/dmtimer.h>

/*
The prescaler is enabled when TCLR bit 5 is set (PRE). The 2n division ratio value
(PTV) can be configured in the TCLR register.

Each internal interrupt source can be independently enabled/disabled in the interrupt
enable register TIER.

When the interrupt event has been issued, the associated interrupt status bit is set
in the timer status register (TISR). The pending interrupt event is reset when the 
set status bit is overwritten by a 1.

The timer rate is defined by:
-Value of the prescaler fields (PRE and PTV of TCLR register)
-Value loaded into the timer load register (TLDR)

timer rate = (0xFFFF FFFF – TLDR + 1) x timer clock period x clock divider (PS)

PTV + 1)
PS = 2
*/

static unsigned long freq , ct, round;

extern struct omap_dm_timer * frequencimeter; // timer reserved to measure frequency

static irqreturn_t gpio4_freqmeter_irq_handler(int irq, void *arg);

static int __init freqmeter_init(void)
{
	int r;
	round = 0; freq = 0 ; ct = 0;
	printk(KERN_DEBUG "Init driver Freqmeter.\n");

	/* request gpios*/
	/* GPIO - P20_1610_GPIO4 */
	if ( omap_request_gpio(4) < 0 ) printk(KERN_ERR "Error init GPIO4 (freqmeter).\n");
	
	/* entrada */
	omap_set_gpio_direction(4,1); /* in */

	r = request_irq(OMAP_GPIO_IRQ(4), gpio4_freqmeter_irq_handler, IRQF_TRIGGER_RISING, "freqmeter", gpio4_freqmeter_irq_handler);
	if ( r < 0 ) {
		printk(KERN_ERR "freqmeter: request_irq() failed.\n");
		return r;
	}
	
	printk(KERN_DEBUG "freqmeter initialized.\n");
	return 0;
}

static irqreturn_t gpio4_freqmeter_irq_handler(int irq, void *arg)
{
	// dummy: 	no interrupt? freq = 0Hz
	//		only one int? freq = 0Hz  
	
	/**	there is interference?: lread INT again
		should be in same logic level */
	if ( omap_get_gpio_datain(4) )
	{
		if(round > 0)
		{
			if(round == 50)
			{
				
				ct = omap_dm_timer_read_counter(frequencimeter);
				omap_dm_timer_stop(frequencimeter);
				ct /= 50;
				freq = 1200000000/(ct +1);
				
				printk("freq = %d\n",(freq/*-8*/));
				round = 0xFFFFFFFF;
				ct = 0;
				freq = 0;
			}
		}
		else			// first read
		{
			freq = 0;
			
			printk(KERN_DEBUG "Iniciou o freqmeter");
			omap_dm_timer_write_counter(frequencimeter,0x0);
			omap_dm_timer_start(frequencimeter);
		}
		round++;
	}
		
	return IRQ_HANDLED;
}

asmlinkage long sys_freq_read(void)
{
	
	return freq;
}

static void __exit freqmeter_cleanup(void)
{
	free_irq(OMAP_GPIO_IRQ(4), NULL);
	omap_free_gpio(4);
}

module_init(freqmeter_init);
module_exit(freqmeter_cleanup);

MODULE_LICENSE("GPL");

Integer to ASCII

Dr. Maykel Alonso January 18, 20132 comments Coded in C
/***** integerToAscii.h *****/

#define BASE_OCTAL			8
#define BASE_DECIMAL			10
#define BASE_HEXADECIMAL		16

#define BUFFER_SIZE			32

char* integerToASCII(long int value, int base);

/***** integerToAscii.c *****/

char* integerToASCII(long int value, int base){
	
	int aux;
	static char buf[BUFFER_SIZE] = {0};

        int isNeg=0;
        if (value == 0) {
                buf[0]='0';
                return &buf[0];
        }
        if (value<0) {
                isNeg = 1;
                value *= -1;
        }	

	for(aux=BUFFER_SIZE; value && aux ; --aux, value /= base){	
		buf[aux] = "0123456789abcdef"[value % base];
	}

	if (isNeg)  {
		buf[aux] = '-';
		return &buf[aux];
	}

	return &buf[aux+1];
}

Incremental Encoder Decode Trick

David January 16, 20131 comment Coded in C
// Incremental encoder decoding.
uint new;
uint old;
bool direction; 
int count=0;

/* Get the latest 2bit sample. */
new = get_new_bits();  // Your function to get new samples.

/* XOR the lower bit from the new sample with the upper bit from the old.*/
direction = (new&1) ^ (old>>1)

/* The "direction" var holds the direction of rotation. */

/* Transfer the new sample to the old sample. */
old = new;

/* We can use this to inc or dec a counter to maintain position of rotation. */
if(direction) counter--; else counter++;

CRC-16 Calculation

Dr. Maykel Alonso January 16, 20138 comments Coded in C
/***** crc16.h *****/
//Tested
#define CRC16_DNP	0x3D65		// DNP, IEC 870, M-BUS, wM-BUS, ...
#define CRC16_CCITT	0x1021		// X.25, V.41, HDLC FCS, Bluetooth, ...

//Other polynoms not tested
#define CRC16_IBM	0x8005		// ModBus, USB, Bisync, CRC-16, CRC-16-ANSI, ...
#define CRC16_T10_DIF	0x8BB7		// SCSI DIF
#define CRC16_DECT	0x0589		// Cordeless Telephones
#define CRC16_ARINC	0xA02B		// ACARS Aplications

#define POLYNOM		CRC16_XXX   // Define the used polynom from one of the aboves

// It calculates the new crc16 with the newByte. Variable crcValue is the actual or initial value (0).
unsigned int crc16(unsigned int crcValue, unsigned char newByte);

/***** crc16.c *****/

#include "crc16.h"

unsigned int crc16(unsigned int crcValue, unsigned char newByte) 
{
	unsigned char i;

	for (i = 0; i < 8; i++) {

		if (((crcValue & 0x8000) >> 8) ^ (newByte & 0x80)){
			crcValue = (crcValue << 1)  ^ POLYNOM;
		}else{
			crcValue = (crcValue << 1);
		}

		newByte <<= 1;
	}
  
	return crcValue;
}

/***** EXAMPLE *****/

unsigned int exampleOfUseCRC16 (unsigned char *Data, usigned char len){

	unsigned int crc;
	unsigned char aux = 0;

	crc = 0x0000; //Initialization of crc to 0x0000 for DNP
	//crc = 0xFFFF; //Initialization of crc to 0xFFFF for CCITT

	while (aux < len){
		crc = crc16(crc,Data[aux]);
		aux++;
	}

	return (~crc); //The crc value for DNP it is obtained by NOT operation

	//return crc; //The crc value for CCITT
}

DS18B20 Interfacing

January 15, 20132 comments Coded in C for the TI MSP430
float get_temp(void);
void reset_18B20(void);
void send_18B20(char data);
unsigned int read_18B20(void);

#define ONE_WIRE_PIN BIT4
#define ONE_WIRE_IN P1IN
#define ONE_WIRE_OUT P1OUT
#define ONE_WIRE_DIR P1DIR

float get_temp(void)
{
    unsigned int temp;
    reset_18B20();
    send_18B20(0xcc);   //send CCH,Skip ROM command
    send_18B20(0x44);
    delay_us(100);

    reset_18B20();
    send_18B20(0xcc);   //send CCH,Skip ROM command
    send_18B20(0xbe);

    temp = read_18B20();
    return((float)temp/8.0);

}

void reset_18B20(void)
{
    ONE_WIRE_DIR |=ONE_WIRE_PIN;
    ONE_WIRE_OUT &= ~ONE_WIRE_PIN;
    __delay_cycles(500);
    ONE_WIRE_OUT |=ONE_WIRE_PIN;
    ONE_WIRE_DIR &= ~ONE_WIRE_PIN;
    __delay_cycles(500);
}

void send_18B20(char data)
{
    char i;

    for(i=8;i>0;i--)
    {
    	ONE_WIRE_DIR |=ONE_WIRE_PIN;
        ONE_WIRE_OUT &= ~ONE_WIRE_PIN;
        __delay_cycles(2);
        if(data & 0x01)
        {
            ONE_WIRE_OUT |= ONE_WIRE_PIN;
        }
        __delay_cycles(60);
        ONE_WIRE_OUT |= ONE_WIRE_PIN;
        ONE_WIRE_DIR &= ~ONE_WIRE_PIN;
        data >>=1;
    }
}

unsigned int read_18B20()
{
    char i;
    unsigned int data=0;

    for(i=16;i>0;i--)
    {
    	ONE_WIRE_DIR |= ONE_WIRE_PIN;
        ONE_WIRE_OUT &= ~ONE_WIRE_PIN;
        __delay_cycles(2);
        ONE_WIRE_OUT |=ONE_WIRE_PIN;
        ONE_WIRE_DIR &= ~ONE_WIRE_PIN;
        __delay_cycles(8);
        if(ONE_WIRE_IN & ONE_WIRE_PIN)
        {
            data |=0x8000;
        }
        data>>=1;
        __delay_cycles(120);
    }
    return(data);
}

Sine Wave Generator

Sathyanarayana Hadadi January 15, 20132 comments Coded in C
/*************************************************************************************************************
sineWaveGeneration
*************************************************************************************************************/
void sineWaveGeneration(unsigned long amplitude, unsigned long frequency, unsigned long time)
{
    const double angularfrequency = (2.0 * pi) * (double)frequency;
    const double pi = 3.141592654;
    double timeperiod;
    const double samplingrate = 48000;
    double displacement;

    //declare values
    
    //obtain omega(the angular frequency)
        // creates a 'for' loop that continues until 'endtime'
    for (timeperiod = 0; timeperiod <= (double)time; timeperiod = timeperiod+(1/samplingrate))
    {
        //creates the sine wave A*sin(wt) by plotting every sample.
        displacement = sin(angularfrequency * timeperiod) * amplitude;
    }
    return;
}

Circular FIFO Buffer

Dr. Maykel Alonso January 15, 20137 comments Coded in C
/***** circularBuffer.h *****/

#ifndef CIRCULAR_BUFFER_H_
#define CIRCULAR_BUFFER_H_

#define BUFFER_SIZE 128
#define TYPE char

// Check if the buffer it is full
bool isFull();

// Check if the buffer it is empty	
bool isEmpty();

// Get the first element from the FIFO queue
TYPE getElement();

// Add an element to the FIFO queue
bool addElement(TYPE data);

// Return the number of Elements that are in the FIFO queue
unsigned char getNumberOfElements();

#endif /*CIRCULAR_BUFFER_H_*/

/***** circularBuffer.cpp *****/

#include "circularBuffer.h"

TYPE Buffer[BUFFER_SIZE + 1]; // It needs 1 extra byte to difference full and empty
unsigned char next = 0;
unsigned char first = 0;

bool isFull(){
	if (getNumberOfElements() == BUFFER_SIZE){
		return true;
	}else{
		return false;
	}
}
	
bool isEmpty(){
	if ( next == first ){
		return true;
	}else{
		return false;
	}	
}
	
TYPE getElement(){
	TYPE theElement = 0;
	if (! isEmpty()){	 
		theElement =  Buffer[first];	
		if ( first != BUFFER_SIZE ){
			first++;
		}else{
			first = 0;
		}		
	}

	return theElement;// Return 0 always if it is empty, must be checked before
}

bool addElement(TYPE data){	
	if (!isFull()){
		 Buffer[next] = data;
		 if ( next != BUFFER_SIZE ){
			next++;
		 }else{
			 next = 0;
		 }
		return true;
	}else{
		return false;
	}	
}

unsigned char getNumberOfElements(){	
	if (next >= first){
		return (next - first);
	}else{
		return (BUFFER_SIZE - next + first);
	}	
}

The 2024 Embedded Online Conference