Configurable Hardware

The Camtasia Studio video content presented here requires a more recent version of the Adobe Flash Player. If you are you using a browser with JavaScript disabled please enable it now. Otherwise, please update your version of the free Flash Player by downloading here.

Today's product developers are being increasingly pressured for internal algorithms, so that embedded systems will be adaptive, and to provide user extension points. These extensions allow a consumer to customize his hardware behavior, as per his rules and preferences. These software defined devices abound in the market today, including software defined radios, custom automatic transmission controllers, and small home or office routers.

Human Machine Interface Development & Integration

Our team can build a rich user interface that runs on a desktop or embedded web server, and controls the embedded device.

We often capture strategic data points, to provide reports and diagnostic feedback, for engineers to measure differences performance between different configurations.

Our experience will ensure that any hardware software integration project will succeed.

Message Patterns

When working on interoperability layers between HMI/HCI and embedded systems, Engineers spend a large percentage of their time implementing custom ICDs, or interface communication documents. These documents contain byte level format for each data transfer object in their embedded application. Using our parsing expression grammar, we leverage a parsing framework that turns several months of complex embedded application interoperability operations down to a couple of weeks. We have worked with asynchronous, synchronous, and transactional message patterns.

Devices and Peripherals

We are comfortable prototyping solutions with LabVIEW and various DAQ boards.

We have worked with the following manufacturers and associated toolchains: Microchip 8/16/32 bit, Freescale 32 bit, and ARM9 microcontrollers and processors.

We have designed applications that interface with the following peripherals: Ethernet TCP/IP networking, ZigBee, General Purpose Input/Output, Analog to Digital Converters, Frequency Measurement, Pulse Width Modulation, Universal Asynchronous Receiver/Transmitter, and Interrupts.

Here is an example of code that sets up control registers for an ADC peripheral when the device boots up.

 
void setup_qadc()
{
	QADC_A.QADC64MCR.B.STOP = 0; 
		// Enable the QADC64 Clock [give it power]
	
	
	QADC_A.QADC64MCR.B.FRZ = 0; // no
			

	QADC_A.QADC64MCR.B.SUPV = 0;
		// do not lock global registers, which include 
		// QADC64MCR, QADC64TEST, and QADC64INT

		
	QADC_A.QADC64INT.B.IRL1 = 0b00000;	
	QADC_A.QADC64INT.B.IRL2 = 0b00000;
		//interrupt level 0


	// Allow general access to the QADC64 registers
	QADC_A.QACR0.B.MUX = 0;						// Set internal mux - 16 possible channels
	QADC_A.QACR0.B.TRG = 0;						// Set the trigger assignments

	QADC_A.QACR0.B.PSH = 0x0b;	// 5 bits
		// prescaler clock high time  (11 + 1) cycles
		// High QCLK Time = (PSH + 1) ÷ FSYS
	
	QADC_A.QACR0.B.PSL=0x07;	//3 bits
		// prescaler clock low time (7 + 10) cycles
		// Low QCLK Time = (PSL + 1) ÷ FSYS
		// FQCLK= 1 ÷ (High QCLK Time + Low QCLK Time)
		// Following settings produce QCLK = 2MHz when the internal frequency, FSYS, is 40 Mhz
		// Conversion time is 7us. [see page 440]
		// When both queues are disabled (scan mode = disabled), it is safe to change the QCLK prescaler values.
		

	// Setting for QUEUE 1
	QADC_A.QACR1.B.CIE1= 0;						// Ensure queue comletion interrupts are disabled
	QADC_A.QACR1.B.PIE1 = 0;					// Ensure pause interrupts are disabled
	QADC_A.QACR1.B.SSE1 = 0;					// Disable Single Scan on Trigger
	QADC_A.QACR1.B.MQ1 = 0b00001; 				// Operating Mode = Software Triggered Single-Scan Mode started when SSE1 = 1.

	
	// Setting for QUEUE 2
	QADC_A.QACR2.B.MQ2 = 0b00000; 				// Operating Mode = Disabled
	

	// Place in queue analog input channels monitoring
	// Command Convertion Word Table - up to 64  

	// Throttle Position Sensor
	QADC_A.CCW[0].B.P = 0;						// do not enter pause state
	QADC_A.CCW[0].B.BYP = 0;					// disable amplifier bypass mode
	QADC_A.CCW[0].B.IST = 0b01;					// take 4 clks periods to sample; affects conversion time;  specifies length of sample window 
	QADC_A.CCW[0].B.CHAN = 0b000000;			// AN0 in non multiplexed mode
	
	// Temperature Sensor
	QADC_A.CCW[1].B.P = 0;
	QADC_A.CCW[1].B.BYP = 0;
	QADC_A.CCW[1].B.IST = 0b01;  
	QADC_A.CCW[1].B.CHAN = 0b111000;			// AN56 in non multiplexed mode					 
}

Example code that reads status registers during runtime.

 
// only called from interrupt. (no infinite loop possibility)
char receive_char()
{
	while(QSMCM.SC1SR.B.RDRF == 0);
			// Loop until Receive Data Register is free

	return (char)QSMCM.SC1DR.R; 
			// Get Data on Receive Register	
}

Example code of our interrupt handling.

 
void InterruptHandler(long cause)
{
	unsigned int LVL0 = 0x40000000;
	unsigned int LVL1 = 0x10000000;
	unsigned int LVL2 = 0x04000000;
	unsigned int LVL3 = 0x01000000;
	unsigned int LVL4 = 0x00400000;
	unsigned int LVL5 = 0x00100000;
	unsigned int LVL6 = 0x00040000;
	unsigned int LVL7 = 0x00010000;
	
	if( cause == 0x500)
	{
		if ((USIU.SIPEND.R & LVL5) == LVL5)
		{	// time processor unit; pta function (frequency capture)
			if(TPU_A.CISR.B.CH1 == 1)
			{
				TPU_A.CISR.B.CH1 = 0;
				Interrupt_OnSpeedSensorFrequencyInput();
			}
			
			if(TPU_A.CISR.B.CH12 == 1)
			{
				TPU_A.CISR.B.CH12 = 0;		
				Interrupt_OnDistributorFrequencyInput();
			}
		}
		
		if((USIU.SIPEND.R & LVL2) == LVL2)
		{	// serial communication interface
			Interrupt_OnCharReceived();
		}
	}
}