The PSoC Hacker Blog - Cypress.com: Blog Posts psochacker@cypress.com.]]> http://www.cypress.com/?id=2314 Getting Started With PSoC Designer http://www.cypress.com/?rID=70504 Here is a video that I created for Getting started with PSoC Designer 5.3. View it in 720p or 1080p for higher quality.

]]>
Thu, 11 Oct 2012 08:59:28 -0600
Introduction to PSoC 1 Architecture and Design Flow http://www.cypress.com/?rID=69919 Here is a video I made on introduction to PSoC 1 architecture and design flow.

]]>
Mon, 01 Oct 2012 00:43:04 -0600
PSoC Designer - Getting Started Video http://www.cypress.com/?rID=39309 Note: As we constantly update our design tools with cutting-edge features, we realize some of the content of this training material may now be obsolete. Please bear with us while we upgrade our training content relative to this.

Here is a video on PSoC Designer Getting Started. This shows how to create a PSoC Designer project to measure an analog signal using a 12 bit ADC and display on LCD. Also a PWM is configured for 1Hz output to blink an LED.  Write to me your feedback to graa@cypress.com

 

]]>
Fri, 14 Sep 2012 03:54:39 -0600
PSoC1 Getting Started Debugging - Part 1 - The Hardware http://www.cypress.com/?rID=68793 Here is a video I made for Getting Started debugging a PSoC1 project.  This is a two part series and in the first part, I have covered the hardware requirements.  The second part that covers the PSoC Designer part of the debugging will follow soon.

Application note "AN73212 - Debugging with PSoC1" provides all the information required to debug a PSoC1 project.

Happy Debugging!

]]>
Mon, 10 Sep 2012 04:15:04 -0600
UART Clock Accuracy Requirement in PSoC 1 http://www.cypress.com/?rID=39848 When using the UART user module in the PSoC 1, the most important parameter for the UART is the clock. The user module data sheet says the clock to the UART should be 8x the baud clock. So, for a 9600 baud rate, the clock to the UART should be 8 x 9600 = 76.8KHz.

In PSoC 1, this clock has to be derived from the SysClk or SysClk * 2. Let us take SysClk for this case and assume a SysClk of 24Mhz. To get a frequency of 76.8KHz from 24MHz, the required divider is 312.5. Unfortunately, we cannot have a fraction in the divider and have to round off to 312 or 313. For a divider of 312, the resulting clock is 76.923KHz. This gives rise to a plethora of questions. Is this clock accurate enough? Will I get bit errors because of the deviation in the clock? What is the maximum tolerance allowed in the clock to UART?

Before we get into the answer to the question, let us first derive the maximum error allowed in the UART clock. Picture below shows the UART RX line and the internal 8x clock. The UART data transfer starts with a Start bit, 8 data bits, optional parity bit and ends with a Stop bit.

 

Ideally, the Receiver samples the RX line at the mid-point of every bit.  If the UART clock has 0% error, then the sampling will happen exactly at mid-point of the Stop bit.  But as the UART clock will have a tolerance, depending on the +ve or ve error on the UART clock, the sampling will happen earlier or later than the mid-point on every bit.  This error keeps accumulating and will result in the maximum error on the Stop bit.  Ideally the maximum error allowed on the Stop bit would be + ½ a bit, ie, 50% of the bit time.  But practically, if we sample earlier or later by 50% of the bit time, we will be sampling at the bit transition.  For systems that have higher bus capacitance and higher rise and fall times, this will create a problem. 

So, allowing for rise and fall times at 20% of the bit time, we have a room of +40% of the bit time in the Stop Bit.  The tolerance allowed on the UART clock is +40% / (No. of Bits).  For an UART with one Start bit, 8 data bits and one Stop bit, the maximum error allowed on the clock would be +4%.  This 4% tolerance has to be split between the devices on the either side of the UART bus.  For example, if a device on one side of the UART bus runs on a crystal at 100ppm, the device on the other side can have a clock tolerance of +3.99%.  Remember, this 4% also is again subject to system performance.  If you are running a very long cable and the UART at a very high baud rate, the rise and fall times may be more than 20% of the bit time and you will have lesser room for error.  AT lesser baud rates and shorter cables, you will have more room for error.

Now let us check the round off error introduced by the divider.  For a 9600 baud, we use a divider of 312 on the SysClk which results in a clock of 76.923KHz against the requirement of 76.8KHz.  The error introduced by this deviation is just 0.1% and is negligible.

The next contributor to the error budget is the tolerance of the clock source which is the IMO.  In most of the PSoCs (CY27x43, CY29x66, CY24x23, etc), the IMO has a tolerance of +2.5% over the full operating temperature.  This is well within the +4% tolerance.  Also, the PSoC boot.asm code writes a factory programmed trim value to the IMO trim register, which further reduces the error of the IMO to <1%.  So, clocking the UART from the IMO will not introduce any problem.

What about the devices which have IMO with a tolerance of >=4% (CY24x94, CY21x34 etc)?  In fact, when you place an UART component in the CY24x94 device, the Design Rule Checker gives a warning that to use an UART, the device should be connected to the USB bus.  When connected to the USB bus, the IMO gets synced to the USB clock and hence will become as accurate as the USB bus clock.  When not connected to USB bus, it runs at +4% tolerance and hence this warning. 
For these devices various options may be considered.

  1. What is the device on the other side of the UART? If the device on the other side of PSoC runs on a crystal, then the complete 4% error margin can be used by the PSoC.  Also, though the IMO is specified for an accuracy of >+4%, after the trim in boot.asm, it will be better than +2%.
  2. What is the slowest baud rate that you can use in the system?  Lower the baud rate, the rise and fall times will occupy lesser part of the bit time and the tolerance of the UART bus will tend towards 5% and you get more room for error.
  3. What is the shortest cable you can use?  Shorter the cable, lesser the bus capacitance.  This will reduce the rise and fall times and the tolerance will tend towards 5%
  4. For the CY8C24x94, if you are not using the USB, then you may consider using other devices like CY8C27x43 or CY8C29x66.
  5. Use an external 24MHz oscillator and connect this oscillator to P1[4].  In the Global Resources select P1[4] as the SysClk source.

With the above considerations, a robust UART communication can be built in PSoC 1.

]]>
Thu, 23 Aug 2012 06:09:03 -0600
Useful Resources to Getting Started with PSoC 1 http://www.cypress.com/?rID=64695 For beginners who are starting to work with with PSoC 1, and for experienced users to get a deeper understanding of some of the basic concepts, here is a collection of useful resources that can get you started with PSoC 1.

AN75320 Getting Started with PSoC 1: This application note provides an introduction to PSoC1 architecture, how PSoC 1 is different from a regular microcontroller,   the programmable analog and digital subsystems, IO structure, PSoC Designer IDE, programming and debugging flow etc.

PSoC Designer Getting Started Video: This video walks the user through the process of creating a simple PSoC Designer project that measures a voltage using an ADC and displays on an LCD and blinks an LED.  

AN73212 Debugging with PSoC 1: AN73212 introduces the elements of the PSoC 1 debugger system and explains how to configure and use them effectively. It provides the user with several common debugging techniques and a troubleshooting guide to help solve common problems, such as stack overflow and memory corruption.

AN32200 PSoC 1 Clocks and Global Resources: A must read to get a grip on the Global resources, this application note discusses in details the flexible clocks and all the global resources like analog reference, watchdog, SMP etc.  

AN50987 Getting Started with I2C in PSoC 1: I2C is one of the most commonly used communication interfaces in embedded systems.  This application note provides a detailed overview of the I2C protocol, the different I2C implementations available in PSoC 1, and advanced information and tips on using I2C in PSoC 1.

AN74170 - PSoC 1 Analog Structure and Configuration with PSoC Designer: This application note discusses in detail the analog resources of PSoC 1 continuous time blocks, switch capacitor blocks, analog reference, analog output buffers etc.  This application note discusses how these blocks are organized inside PSoC 1, the interconnectivity between these blocks and external pins, various analog reference combinations,     global resources that affect analog blocks etc.

AN2041 Understanding Switched Capacitor Blocks in PSoC 1: A switched capacitor blocks is the most flexible analog resource in PSoC 1.  A switched capacitor block lets the user build most commonly used analog peripherals like ADCs, DACs, Filters etc to very advanced applications like synchronous rectifiers, analog modulators and demodulators, FSK generators etc.  This application note explains in detail the theory behind switched capacitor topology and how the PSoC 1 switched capacitor blocks can be used to build all these useful peripherals.  This is one of my most favorite application notes.

Happy Reading!

]]>
Thu, 28 Jun 2012 03:09:39 -0600
PSoC 1 SC Block Applications - Precision Full Wave Rectifier http://www.cypress.com/?rID=61340 I made a video showing how a precision full wave rectifier may be created in PSoC 1 by configuring a Switched Capacitor block as a modulator.

Execercise to the User:

  1. Set the ASign parameter of the SCBlock to "Positive" and observe the result
  2. Set the ACap value to 8, 24 and 31 and observe the result.
  3. Set the Polarity of the Comparator to Negative and observe the result.

For more details about Switched Capacitor blocks, refer below application note.

AN2041 - Understanding PSoC 1 Switched Capacitor Analog Blocks

 

The project file for the video may be found below.

PSoC Designer Project - Precision Rectifier

]]>
Thu, 12 Apr 2012 21:11:55 -0600
Thermal Management Using PSoC 1 http://www.cypress.com/?rID=61221 With its flexibile Analog and Digital resources, PSoC 1 is a very strong candidate for Thermal Management applications.  The PSoC can measure temperature from various types of temperature sensors like Diodes, Analog sensors, I2C based sensors, PWM based sensors and 1 wire sensors.  PSoC can implement a closed fan controller function by using 8 or 16 bit PWMs to drive fans and 16 bit timer to measure speed of the fan from the tach signal provided by some fans.

This video shows how a thermal managament application may be implemented using PSoC 1. 

 

 

More information on the kits used may be found in the below links.

CY8CKIT-001 PSoC Platform Development Kit

CY8CKIT-036 Thermal Management Expansion Board

 

The project used in the demo may be found below.

PSoC Designer Project - Thermal Management

]]>
Sat, 31 Mar 2012 00:50:06 -0600
Calibrating Amplifiers and ADCs in PSoC 1 http://www.cypress.com/?rID=60945 In today s world of mixed-signal systems, many applications require analog quantities including but not limited to voltage, current, temperature, pressure, acceleration, pH, flow, and ECG to be measured and processed. The field of uses ranges from lab and medical equipment operating in controlled environments to industrial equipment running under harsh operating conditions. The analog signals to be measured can range from a few micro-volts in ECG systems to thousands of volts in electricity generation plants.

Unfortunately, there is no such thing as an ideal converter in the real world, where systems have to contend with errors that are introduced into the system and affect the ADC s output. The most important errors are offset and gain errors.  

Refer graph below.  This is a plot of an 8 bit ADC with a range of +2.5V.  X axis denotes the input voltage and Y axis denotes the ADC counts.  The blue line is the ideal ADC output. The red line is the actual ADC output.  Notice the actual output is shifted from the ideal.  This shift is called the offset error.


 
All operational amplifiers have a finite offset voltage at the input.  This offset voltage gets added to the input signal, gets amplified by the amplifier s gain and manifests at the output.  Apart from the amplifier stage, the ADC also has its own offset voltage which adds to the system error.  Offset error is an additive error and can be easily removed from the system.

Graph below is the plot of the same 8 bit ADC with the +2.5V range.  Note that the slope of the actual output is now different from the slope of the ideal output.  This shift in slope is called the gain error.


 
These errors may be removed from a system using many calibration techniques like:

  • Correlated Double Sampling
  • Two-point Calibration
  • Gain calibration using external reference. 

PSoC 1, with its flexible analog resources and routing makes it very easy to implement all of the above calibration techniques.  Depending upon the application, one or more of these methods can be combined to achieve maximum accuracy.
Recently, I, with my friend and colleague Pushek Madaan, wrote an article on this topic in EETimes.  The article may be found in the following link.

Calibrating Amplifiers and ADCs in SoCs

The article in PDF format and the PSoC Designer projects for the Correlated Double Sampling and Two-point calibration technique are attached here in this post.

Happy Signal Conditioning!!

 

Calibrating Amplifiers and ADCs in SoCs - PDF Article

PSoC Designer Project - CDS Calibration

PSoC Designer Project - Two Point Calibration

]]>
Fri, 30 Mar 2012 23:23:40 -0600
Cool PSoC3 Applications - Voltage Controlled Oscillator http://www.cypress.com/?rID=43971 With a handful of PSoC3 resources and an external capacitor, a Voltage controlled oscillator can be created.


Pin "Cint" is configured as both Digital and Analog pin with a drive mode Open Drain drives low. When output of Comparator is High, IDAC output is connected to the pin.  When comparator output is Low, the pin shorts to Ground.

IDAC – configured as a source – charges an external capacitor connected to "Cint". When the capacitor voltage crosses input voltage Vin, comparator output becomes low (comparator is set for inverted logic) and discharges the capacitor. As capacitor voltage becomes zero, the comparator output becomes high and IDAC starts charging the capacitor. The cycle continues and we get an oscillator whose frequency is inversely proportional to Vin.  The circuit has excellent “Period vs. Vin” linearity.

For a given input voltage, the combination of IDAC value and external capacitor determines the maximum Period (1/f) of the output.  We know that when a capacitor is charged using a constant current, the time taken to charge to a known voltage is

t = C * V / I

For example, if the maximum period value is desired to be 500uS for an input voltage of 2.5V, for an IDAC value of 1uA, the value of C can be calculated:

C = (500uSec * 1uA) / 2.5V = 200pF


The comparator is synchronized to a clock.  The period of the clock should be long enough to discharge the capacitor.  Too high a clock frequency, the capacitor may not discharge completely.  Too low a clock frequency, the % of the "discharge time" to "charge time" will increase and will reduce the linearity.  The value of the clock will also depend on the value of the capacitor.  Higher value of capacitor will require a longer discharge time.

Selecting the right combination of IDAC, Capacitor and the SyncClock is an interesting exercise left to the user.

The project for the above can be found here.

]]>
Mon, 13 Feb 2012 00:30:18 -0600
ISSP: Why Doesn’t It Program http://www.cypress.com/?rID=38364 “Can’t Acquire Device”, “Verify Failed”, “Checksum Error”, “Device not in database”.  These are some of the errors the PSoC Programmer throws at users when programming a PSoC In System.  When you dedicate the P1[0] and P1[1] pins exclusively for ISSP, there usually is no problem in programming the chip on board.  But the trouble begins when you share P1[0] and P1[1] for other functions.

The most commonly encountered problem in ISSP is when P1[0] and P1[1] are used for I2C.  In programming mode, both SCLK and SDATA pins of the PSoC are configured in Pull Down mode with an internal 5.6K pull down resistor.  There is no issue with the SCLK line as the programmer always drives the SCLK line.  But things are different with the SDATA line.  When the programmer is reading information (like device ID, verify, checksum etc), the PSoC has to drive the SDATA line.  The external I2C pull up resistor forms a potential divider with the internal pull down resistor and does not allow the PSoC to drive LOW on the SDATA line.  This results in a plethora of errors mentioned before.

There are various approaches to solve this problem.

  • The first and the best “DO NOT USE THE ISSP PINS AS I2C”.  Use P1[5] and P1[7] instead.
  • If you are compelled to use the ISSP lines for I2C as well - like when you use a CY3240 I2C USB bridge on the ISSP header for debugging - try isolating the I2C pull up resistors from the SDATA line using a jumper when programming.
  • If you cannot implement the above because of board space problem, add an external load resistor on SDATA line to GND on the ISSP Programmer.  This resistor will apply in parallel with the internal pull down resistor of the PSoC and will reduce the effective resistance and reduce the potential divider effect.  The value of this external resistor will depend on the value of the I2C pull up resistors.  The criteria is that when PSoC drives a LOW on the pin, the potential divider should drive a voltage less than VIL level of the programmer (less than 0.6V should be fine).  Usually a value of 500 ohms to 1K should solve the problem.  Below is a picture on a hack on MiniProg to add the 1K pull down resistor based on a post in psocdeveloper forums a few years back.  As I could not locate the post, I had to risk one of my own programmers.

If the SDATA or SCLK line is configured as an input pin and is driven by a low impedance source, this will load the programmer.   So, always use the SDATA and SCLK pins as output pins driving a high impedance load.  This will prevent the programmer getting loaded.

Do not use direct capacitive loads on the ISSP lines as this will affect the rise and fall times of the programming signals and will affect programming.

Check out AN2014.  This application note provides some details about the ISSP programming, pin loading etc.

Happy ISSP Programming!!

]]>
Wed, 30 Nov 2011 00:20:54 -0600
Measuring a Negative Voltage Using PSoC1 http://www.cypress.com/?rID=50815 One of the most common questions I come across is “How do I measure a negative voltage using PSoC?”  For example, I have a +1V signal that I need to measure using PSoC ADC.  But the PSoC will not take any voltage below VSS.  How do I measure the negative portion of the input signal? 

The solution depends on the answer to two questions. 

Is the signal ground isolated from PSoC ground (VSS)? 
Is the signal AC or DC?

Signal Ground Isolated from PSoC Ground

If the signal ground is isolated from VSS of PSoC, then for both AC and DC input signals, the solution is simple and same.  Bring out AGND to an external pin and then feed the signal with respective to this AGND.

In the schematic above, the internal AGND is brought out on P0[5] using the Analog buffer and the signal is connected between this AGND and the PSoC input.  Set the reference of the PGA (if you are using a PGA to amplify the signal) to AGND and the DataFormat of the ADC to “Signed” and the PSoC is now ready to measure a –ve signal.
More about bringing out AGND to an external pin can be found in the below article.

Bring out AGND to an external pin

Signal Ground is Same as PSoC Ground – AC signal

If the signal ground is same as VSS, and if the input signal is AC, then the signal reference can be shifted from VSS to AGND by using a capacitor and a resistor.

In the above schematic, AGND is brought out to P0[5].  The signal to be measured is connected to the PSoC input through capacitor “C” and the PSoC input is biased to AGND by resistor “R”.  C and R form a high pass filter and hence should be selected in such a way that the input signal is passed without attenuation.  Set reference of the PGA to AGND and DataFormat of ADC to Signed.

Signal Ground is Same as PSoC Ground – DC Signal

When the input signal is DC and the signal ground is same as VSS, then the input can be shifted to AGND by biasing the input to VREFHI.

In the above circuit, the input signal is connected to the PSoC input through resistor R1, and the input of the PSoC is biased to VREFHI using R2.  VREFHI can be brought out to a pin the same way as AGND is brought out, either by using the RefMux user module, or by writing to the ACBxxCR2 register. 

With this circuit, the input signal will be lifted to AGND and attenuated by a factor of 2.  This method works for references that have VSS as REFLO, ie (Vbg + Vbg), (Vdd/2 + Vdd/2) and (1.6Vbg + 1.6Vbg). 

For example, for a reference of (Vbg + Vbg), the Analog Ground is at 1.3V and VREFHI is at 2.6V.  For a +1V input, following are the voltage levels on the input of PSoC for various input signal voltage levels.

Vsignal V on P0[1] w.r.t AGND
-1V 0.8V -0.5V
0V 1.3V 0V
+1V 1.8V +0.5V

From the above table, it is clear that the input signal gets shifted to 1.3V (AGND) and is attenuated by a factor of 2.  One side effect of this method is the difference between the shift created by the resistor network and the internal AGND will be amplified by the PGA.  But this can be compensated in firmware.

Depending on the type of input signal and isolation between signal and PSoC grounds, one of the above methods may be used to measure a –ve signal using PSoC.

 

]]>
Sat, 30 Apr 2011 10:09:26 -0600
PSoC Creator Getting Started Video - My First Video http://www.cypress.com/?rID=38776 Here is my first attempt in creating a technical video.  This is a getting started video for PSoC Creator, where I have explained how to create an ADC project to measure and display an analog voltage for PSoC3 using the PSoC Creator.  Watch it in full screen mode for a clear view of the screen capture.

Please watch and send me your feedback to graa@cypress.com.

 

]]>
Wed, 20 Apr 2011 10:45:58 -0600
Controlling a Latching Solenoid using a PSoC http://www.cypress.com/?rID=49607 Back to the blog world after a long period of inactivity. In the past few months, I have had a chance to work on a very interesting project for our CEO T.J. Rodgers.  He is donating 152 wine fermenters to the U.C Davis School of Enology and Viticulture.   A couple of articles that talk about the project: Blending Science With Wine, UC Davis claims world’s greenest winery

An important part of the fermenter is a temperature controller that controls the temperature of the fermenting grape juice – also known as “Must” – during the fermentation process.  The stainless steel drum that holds the ”must” is surrounded by a jacket through which cold or warm water is passed.  A PSoC is used to sense the temperature of the “must” using a thermistor, and based on the desired set point, controls the flow of cold or warm water through the jacket to maintain the temperature of the “must”.  The PSoC controls the water flow by operating a solenoid valve connected to the outlet port of the jacket. 

In this blog post, I am going to discuss the valve control section of the temperature controller.  This can be used in many other interesting applications like automatic garden irrigation, bathtub overflow control etc.

The primary design challenge was that the temperature controller was battery operated.  Because of this, a continuously on solenoid valve cannot be used.  The solution was a latching solenoid valve from Orbit.


This valve is used in commercial water sprinklers.  The valve has an inlet port and an outlet port for water.  A plunger opens or closes the valve.  This plunger is operated by two magnetic coils.  Energizing one of the coils with a 15V/20mS pulse opens the valve.  Once on, the valve latches and stays on without any further need for power.  Energizing the other coil with the same pulse closes the valve and the valve latches and stays closed.  The schematic of the valve control is shown below.
 

LT1303 is a charge pump, which is used to step up the 3.5V - 4.5V battery voltage to 15V and charge C6, a 2200uF capacitor.  J3 is a socket for the Orbit valve.  The common is connected to the +ve of the 2200uF capacitor.  The other two pins are connected to the drain of T1 and T2, N Channel MOSFETs.  Applying a pulse to the gate of these transistors will discharge the charge in capacitor through the corresponding coil.  Let us have the look at how the PSoC controls this circuit.

The PSoC controls the charge pump through the CH_PMP_SHDN and VB_FB signals.  CH_PMP_SHDN is a GPIO pin configured as StdCPU/Strong and turns on or off the charge pump.  VB_FB is the feedback signal used to sense the voltage on the 2200uF capacitor.  Figure below shows the PSoC Designer resource placement for the valve control.

 
A comparator is used to compare VB_FB with a fixed threshold generated by a DAC6.  The voltage on the 2200uF capacitor is derived by the formula.

Vout = Vref/10K * 160K

where
Vout = Voltage on the 2200uF
Vref = Comparator reference voltage

When the voltage across the 2200uF cross the desired output, the comparator goes high, and the PSoC turns off the charge pump and generates a 20mS pulse on gate of the respective MOSFET to turn On or Off the Orbit valve.

Following code is used to turn on the valve. 

    // Enable the Charge Pump
    CH_PMP_ENABLE;
   
    /* Set Analog reference power to SC On / Ref Med */
    ARF_CR |= 0x06;
   
    /* Start the CMP and DAC modules */
    CMP_Start(CMP_MEDPOWER);
    DAC_Start(DAC_MEDPOWER);
    DAC_WriteBlind(26);
   
    /* A small delay for the DAC and comparator to stabilize */
    DelayMs(5);
   
    /*     Wait for the comparator output to go high
        When comparator output becomes high, it means Vboost is around 18V */

    while(!(CMP_CR0 & 0x80));
   
    // Disable the Charge Pump
    CH_PMP_DISABLE;
   
    // Set the VALVE_ON GPIO
    VALVE_ON_Data_ADDR |= VALVE_ON_MASK;
   
    /* Switch off the CMP and DAC */
    CMP_Stop();
    DAC_Stop();
   
    /* Set analog reference power to all off */
    ARF_CR &= ~0x07;

    // 20mS Delay
    DelayMs(20);
   
    // Clear the VALVE_ON GPIO
    VALVE_ON_Data_ADDR &= ~VALVE_ON_MASK;

Enable the charge pump, switch on the comparator and DAC, wait for the comparator output to go high, disable the charge pump, turn off comparator and DAC and switch on the VALVE_ON GPIO for 20mS.  This will turn on T1 and discharge C6 through the On coil thus turning on the valve.  Similar code is used for turning off the valve where T2 is switched On.

Stay tuned for more interesting topics on the Fermenter!

]]>
Mon, 21 Mar 2011 11:17:06 -0600
Buy One Get Three Free - Making Four VDAC8s from One http://www.cypress.com/?rID=43474 In the recent FAE Conference held in the 3rd week of May 2010, I had a chance to attend a session on “Analog Signal Chain” taken by our Analog experts Dennis and Mark. They showed some really cool tricks using the PSoC3 analog. Some of this stuff was really amazing.

In a couple of my earlier posts, I had talked about doing higher resolution DACs using Parallel DACs and Dithering. This time, Mark showed us the trick to create four DAC outputs using a single DAC, the SC/CT blocks, an LUT and the DMA.


The four SC/CT blocks are configured as Track and Hold circuits whose inputs are connected to the VDAC8.  A four byte array in the RAM holds the values for the four DAC outputs. The DMA reads from this four byte array and writes to the DAC in sequence. An LUT component generates the trigger for the DMA and the Track and Hold circuits. The sequence goes like this.

DMA updates VDAC with the first value, LUT generates the strobe for the TrackAndHold1 and the output of the DAC is held on output1.
The LUT generates a trigger to the DMA which updates DAC with the second value. LUT generates a trigger to TrackAndHold2 and Output2 now has the 2nd DAC value.
This repeats for all the four DAC values and the cycle continues.

The refresh rate is chosen fast enough such that there is very little droop in the TrackAndHold outputs. Also, there is no CPU overhead as everything is taken care of by the DMA. The only overhead for the CPU is to update the RAM array with the desired DAC value. As the TrackAndHold has low output impedance, there is no need to buffer the outputs.

Coming soon is an Application Note on this cool trick.

]]>
Thu, 27 May 2010 18:55:29 -0600
The Lone Cypress Tree – A Symbol of Stability http://www.cypress.com/?rID=43193 Last week end – this is my first visit to the US – I had a chance to visit the 17 Mile Drive in Monterey Bay.  My friend and colleague Palani took a great risk and agreed to teach me to drive on the US roads, especially the freeway. 

The Teacher and the Student

He taught me lane discipline, important road symbols, looking over shoulders before switching lanes, entering the freeway at 60mph (I would never dare do this in India) and many more.  I did throw him a few scares by driving on the left side of the road a couple of times (deserted roads of course) and once changing lane without looking behind my shoulder.  Thanks to his tutelage I have learnt the ropes and now I am able to drive in San Jose roads without getting honked at (just once in the past 5 days).

The Lone Cypress Tree

This is “The Lone Cypress Tree” which stands on a rock for more than 200 years (some web sites claim more than 250 years).  I learnt from a colleague Don that this tree which stands as a symbol of stability weathering time is the inspiration behind the Cypress Logo.
Here are some more interesting photos from this trip.


The majestic Brown Pelican in flight

 


This Beechey Ground Squirrel was quite bold and posed for me

 


A Western Gull resting on a rock

]]>
Fri, 07 May 2010 16:11:16 -0600
My Favorite PSoC Hacks - Connect AGND to a Pin http://www.cypress.com/?rID=43132 In this new series I will share with you some of my favorite PSoC Hacks – like cool things you can do by simple register writes or fixes to some of known issues in PSoC.

Usually, in systems that involve bipolar signal measurement, you will have to bring out the internal AGND to an external pin so that the input signal may be referenced to AGND.  The simplest method to do this would be to use the RefMux user module (from the MUXs category in the User Module catalog) and set the reference to AGND – see figure below.

However, the disadvantage with this method is that this occupies one CT block.  If your design has PGAs INSAMPs or CMPPRGs that occupy all the CT blocks, then there is no place for the RefMux user module.   There is another way – The Hacker’s way – to bring out AGND.  See the block diagram of a CT block below.

The TestMux inside the CT block can be configured to connect the AGND to the Analog bus (The RefMux UM uses this resource).  Provided a resource placed in the CT block does not use the Analog bus, the same CT block may be used to bring out AGND by enabling the TestMux using register writes.  For example, if you have a PGA placed in ACB00, the TestMux in ACB00 can be used to connect AGND to the Analog Bus and to P0[5]. 

Enable the Analog buffer in Analog Column 0 and write following 2 lines of code in the beginning of main.c to connect AGND to the analog bus.

ACB00CR2 &= ~0x1C; // Clear the testmux bits
ACB00CR2 |= 0x14;  // Enable Testmux and select AGND as output of TestMux

REFHI and REFLO may be brought out the same way:

ACB00CR2 |= 0x18; // Connect REFLO to analog bus
ACB00CR2 |= 0x1C; // Connect REFHI to analog bus


Remember, for this to work, the analog bus should not be used by either the CT block or the SC blocks in that column.

Stay tuned for more hacks!!

]]>
Wed, 05 May 2010 10:20:17 -0600
Google Search in Cypress Website http://www.cypress.com/?rID=40438 One major issue that most people complain about Cypress website is the inefficiency of the search engine.  It is very difficult to locate the desired information using the default search engine.  For example, typing "change uart baud rate" in the keyword search box returns 1221 results.  The search result contains everything from Data sheets to Application notes, but the KB article that I was looking for, "Changing UART Baud Rate on the Fly" appeared on the 10th page of the search result as the 901st entry.  This makes it almost impossible to locate any information.

But all is not bad.  There is good news.  Google search is available as an alternate search engine in Cypress website.  In the search result page, you can find a link to Google search on the top right corner "Search Tip: Didn't find what you were looking for? Try our Google Search". 

I clicked on the Google Search link and... Voila!! The KB that I was looking for is now the very first entry in the search result.

I hear you asking "Then why not make Google Search as the default search engine?"  I got news that the web team is working on this and you should see Google as the default search engine in a couple of weeks' time.

So, looking for some information on Cypress website?  Google it!!

]]>
Thu, 18 Mar 2010 06:49:52 -0600
To Toggle or Not To Toggle... http://www.cypress.com/?rID=40643 // Start USB for 5V operation and wait till enumeration is complete
USBFS_Start(0, USB_5V_OPERATION);
while(!USBFS_bGetConfiguration());

// Load the IN endpoint with data with no toggle
USBFS_LoadInEP(1, Data, 8, USB_NO_TOGGLE);

while(1)
{
   ...
   // Other code
   ...
   // Wait till EP1 becomes free
   while(!USBFS_bGetEPAckState(1));

   // Load EP1 with gamepad report
   USBFS_LoadInEP(1, Data, 8, USB_TOGGLE);
}

Above code shows the general program flow when using an USBFS user module to send data to the PC using an IN Endpoint.  If you notice, the USBFS_LoadInEP function call before the while loop uses “USB_NO_TOGGLE” and the call inside the while loop uses “USB_TOGGLE”.  What is this TOGGLE and NO_TOGGLE?  What is the significance of these constants?  I can understand from the above code that the first time I call the USBFS_LoadInEP function, I have to use NO_TOGGLE option and TOGGLE for further transactions.  Why is it so?  These are some of the questions a first time user of USB faces. 

In the USB bus, data is transferred from the Peripheral to Host and vice versa using Data Packets.

 

A data packet comprises of a DATA0 / DATA1 flag, the payload data and the CRC of the payload data.  The DATA0 / DATA1 flag is used to synchronize the data delivery.  Whenever a data packet is delivered, the receiver checks the DATA flag with its own internal flag.  The transaction is successful only if the flag matches.  At the time of enumeration, both the peripheral and the host set the Data flag to DATA0.  When the peripheral sends the first data packet, it sends it with DATA0 flag.  The host on receiving the packet verifies that the received packet has the DATA0 flag and its own flag is also DATA0.  So, the transaction is successful.  Immediately, the host toggles its internal flag to DATA1.  The peripheral when sending the next data packet should also toggle its own data flag and send the data packet with Data1 flag.  This toggling continues on all successive transactions.


In the PSoC, the constants USB_TOGGLE and USB_NO_TOGGLE tell the USBFS_LoadInEP function whether toggle the DATA flag before sending the data to the host.  When the USB is started and enumeration is complete, the USB hardware sets the DATA flag to DATA0.  As the very first data packet should go with DATA0, the DATA flag should not be toggled and hence the USB_NO_TOGGLE option should be used.  All further transactions will require the DATA flag to be toggled and should use the USB_TOGGLE option.

The sample code given in the beginning has one flaw.  If the data is not initialized at the time of calling the LoadInEP function outside the while loop, the host will receive this uninitialized data as the first packet.  This may be fine in certain applications like mouse where a data packet with zeroes does not affect the system. 

But in other systems where the peripheral responds with data to the host when host sends some commands, then this call to LoadInEP with dummy data may not be good.  The solution is to use a flag in the application and use NO_TOGGLE for the very first data packet and use TOGGLE for all further data transfers.  The code will now look like this.

BYTE FirstPacket;  // Flag to indicate first packet

// Start USB for 5V operation and wait till enumeration is complete
USBFS_Start(0, USB_5V_OPERATION);
while(!USBFS_bGetConfiguration());

FirstPacket = 1;

while(1)
{
   ...
   // Other code
   ...  

   // Wait till EP1 becomes free
   while(!USBFS_bGetEPAckState(1));
   if(FirstPacket)
   {
      // This is the first packet
      // Load the IN endpoint with data, and do not toggle the DATA flag
      USBFS_LoadInEP(1, Data, 8, USB_NO_TOGGLE);
      FirstPacket = 0;
    }
   else
   {
      // This is not the first packet
      // Load the IN endpoint with data, and toggle the DATA flag
   USBFS_LoadInEP(1, Data, 8, USB_TOGGLE);
   }
}

]]>
Thu, 18 Mar 2010 06:46:19 -0600
Recovering from a Watchdog Reset http://www.cypress.com/?rID=40391 Many times in applications using the Watchdog timer, there may be a requirement to detect if a reset occurred due to Watchdog or POR / XRES and the application may either start fresh in case of POR / XRES or recover and start executing from the state when the watchdog reset occurred.

DETECT THE SOURCE OF RESET

The first requirement is to find out the source of reset.  This can be done by checking the WDRS bit in the CPU_SCR0 register.  This bit is set in case of a watchdog reset event.  The below code in the beginning of main.c can be used.

if(CPU_SCR0 & CPU_SCR0_WDRS_MASK)
{
    // Reset is due to Watchdog
}

PRESERVE GLOBAL VARIABLES

In order to recover from a watchdog reset and resume the application, it is necessary that the Global variables be preserved when the watchdog reset occurs.  This can be done by setting the IRAMDIS bit in the CPU_SCR1 register.  When this bit is set, all the cells marked “??” in the below table are preserved during a Watchdog reset (taken from Technical Reference Manual Section 3).


Add the below code in the beginning of main.c to preserve the content of these RAM locations.

CPU_SRC1 |= CPU_SCR1_IRAMDIS;

There are a few more points to consider in the usage of the IRAMDIS bit.

When using C as the programming language, the boot.asm sets all the global variables to 0x00.  This has to be disabled.  The boot.asm has a constant “C_LANGUAGE_SUPPORT”, in the beginning.  Set this constant to 0 to disable the global initialization.  Change the value of the constant in boot.tpl in the project folder, save boot.tpl and Generate Application.  As “boot.asm” is generated from boot.tpl, the change will now reflect in boot.asm.

Only RAM locations from 0x03 are preserved when IRAMDIS is set.  Locations 0x00, 0x01 and 0x02 will still get reset.  So, no global variable should be placed in these locations.  This is highly unlikely to happen though.  By default all the global variables are placed in the area “bss”, which follows the areas “virtual_registers” (used by the compiler to store virtual registers) and “InterruptRAM” (used for user module variables).  These areas will mostly occupy the locations 0x00 to 0x02 and more.  In the remote possibility that both these areas are empty and “bss” starts from 0x00, you will have to create a custom area and place it at a location above 0x02, and place all the locals in this area.  More details about placing globals in the desired RAM location can be found in this KB article.  The location of the RAM areas can be checked in the project map file (with .mp extension) in the “output” folder in the project.

Only RAM Page-0 gets cleared by resets and need be preserved by IRAMDIS bit.  In devices with more than 256 bytes of RAM, Page-1 and above are not changed by a watchdog reset.  So, locating all the global variables in RAM Page-1 or above will not require setting the IRAMDIS bit.

ADDING SOME MORE RELIABILITY

What if the event that caused the watchdog reset (RF interference or a power supply spike), also corrupted some of the global variables?  We need to be able to detect this and start the program normally.  Create a checksum of all the global variables that are critical to the program and store it in another variable.  Every time one of the global variables is updated, update the checksum as well.  On watchdog reset, calculate the checksum of all the global variables and compare it with the checksum variable.  If the calculated value matches the stored value, then the global variables are intact and the process may proceed to recover from the last state.  If the checksum values do not match, then the process can start from beginning.

The code in the beginning of main.c will look something like this:


CPU_SRC1 |= CPU_SCR1_IRAMDIS; // Set the IRAMDIS bit

if(CPU_SCR0 & CPU_SCR0_WDRS_MASK) // Check the source of reset
{
   Reset is due to Watchdog.
   Calculate the checksum of the global variables.
   If Checksum matches:
      Resume from the last state
   Else
      Start application from beginning
}
else
{
   Reset is due to POR / XRES.
Start the application from beginning
}

]]>
Mon, 01 Mar 2010 06:52:21 -0600
Swamy and Friends http://www.cypress.com/?rID=40382 Recently, there was an article in Hindustan Times (a leading Indian Newspaper) titled “Swamy and Friends”.  It is about my long time friends and colleagues Narayana and Geethesh. 

Our friendship goes back 15 years when we were neighbors in Mysore in the late nineties.  Narayana was working as a Data Entry Operator in Central Excise of India; Geethesh was the Head of Department of the Electronics in a very small Polytechnic.  Narayana had a very strong logical mind which made him a great programmer, but absolutely no electronics background.  Geethesh being a lecturer had a strong hardware background.  During a leisurely conversation, I suggested them to combine their talents and take part in the Circuit Cellar Design contest.  Their combination clicked and they won Honorary Excellence in their very first contest.  There was no stopping them after that.  They became PSoC consultants and then joined Cypress India as the first PSoC Applications Engineers - now the PSoC Applications team is 20+ strong.  

From a guy who had absolutely no electronics background - he knew nothing about resistors, capacitors, voltage and currents - today Narayana is an expert in capacitive sensing.  He talks about Delta Sigma modulators, PRS generators, EMI etc, holds a patent for implementing a matrix keypad with minimum number of sensors and plans to file a few more.  He is my one stop for reference for capacitive sensing.  Geethesh today is part of the Technical support team leading a team of 6 engineers and is a mentor who trains and guides the young engineers in the team.  I attribute their success to their hard work, sincerity and perseverance and am proud to be their friend.  

Thank you PSoC for bringing us together!!

Swamy and Friends - Hindustan Times Article

 

]]>
Thu, 25 Feb 2010 23:59:42 -0600
PSoC3 Workshop at BITS Pilani Goa Campus http://www.cypress.com/?rID=40362 A couple of weeks back I and my colleague Kannan - the guy who gave me the idea for the Dithered DAC - had been to BITS Pilani Goa campus for conducting a PSoC3 workshop. 

We conducted the workshop during the Quark 2010 Tech Fest for which Cypress is one of the sponsors.  96 students attended the workshop.  In the morning we had a theory session on PSoC3 architecture.  In the afternoon, we had three hands on sessions where students created PSoC3 projects starting from basic blink an LED using firmware to creating two out of phase PWMs and making an LED to brighten and dim from the phase shift.  It was a great experience to be in college and teaching students.  Seeing the enthusiasm of the students and the way they were enjoying college life, I got a nostalgic feeling about my college days 18 years back.  If only I could turn time back... (sigh...)

Here are a few photos from the workshop.

Quark 2010 Mascot

The theory session by Kannan

The Practicals

Also, on this occasion, three fighter planes from the Idian Navy presented an air show.  It was awesome to see the three jets flying at Mach speed spewing colored smoke from their tails and performing various maneuvers with split second timing. Here are a few photos.

 

]]>
Fri, 19 Feb 2010 21:06:10 -0600
Connecting a Multiple Wired Bus in PSoC Creator - An Update http://www.cypress.com/?rID=40109 After I published my video on Connecting Multiple Wired Hardware Bus in PSoC Creator, I received a feedback from PSoC Sensei that there are easier methods to get this done.  He even took the trouble to create a small video of screen capture showing how to do this and sent this to me.  Based on his feedback, here is an updated version of the video.

 

Thank you, PSoC Sensei!

]]>
Sat, 16 Jan 2010 00:24:30 -0600
Connecting a Multiple Wired Bus in PSoC Creator http://www.cypress.com/?rID=40097 When I was working on the project to test the High Resolution Dithered DAC, I had to connect two control registers to the input of a 2:1 8 bit wide mux and the output of this mux to the Data bus of the DAC.  After many failed attempts to create a bus connection, one of the PSoC3 geeks taught me how to do this in the PSoC Creator.  I created this video so that it may be useful to others who come across the same requirement.  Hope you enjoy the video.

 

An updated version of this video is available in this post.

]]>
Sat, 16 Jan 2010 00:10:54 -0600
PSoC 1 GPIO Demystified - Part 1 http://www.cypress.com/?rID=39496 GPIOs play an important role in creating a bridge between the internals of a microcontroller to the external world.  Let us take a look at the important features of PSoC 1 GPIO and application scenarios.  Because of the large amount of information to be covered, I have split this into a two part series.

Part-1 is about various features of the GPIO like the Drive modes, GPIO registers, Interrupts and the PSoC Designer interface to configure the GPIO.  This is mostly boring stuff from the Technical Reference Manual. If you would like to get to the interesting stuff, skip to Part-2 which covers application scenarios like writing to a GPIO, reading from a GPIO, Read Modify Write Instructions and writing a GPIO ISR.

DRIVE MODES

PSoC1 GPIO pins can be configured into one of 8 drive modes.


#

Drive Mode

HIGH

LOW

Comments

1

Pull down

Strong

Resistive

Input / Output

2

Strong

Strong

Strong

Output

3

High Impedance

HighZ

HighZ

Input (Schmitt Trigger enabled)

4

Pull Up

Resistive

Strong

Input / Output

5

Open Drain High

Strong

HighZ

Input / Output

6

Slow Strong

Strong Slow

Strong Slow

Output (Slope controlled)

7

High Impedance Analog

HighZ

HighZ

Analog Input / Output

8

Open Drain Low

HighZ

Strong Slow

Input / Output, I2C

Strong and Slow Strong are used as outputs.  The Slow strong mode introduces a slew rate control on the pin that increases the slope on the rising and falling edges of the pins thus reducing EMI and RFI radiations.

HighZ mode is used as input for both analog and digital signals and also for analog output.  HighZ Analog mode is used for Analog input and output.  Remember, in the HighZ Analog mode, the Schmitt trigger circuit on the digital input path is disabled and hence the pin cannot be used to read digital signals nor will it generate interrupts.

Pull Up, Pull Down, Open Drain High, and Open Drain Low can be used as Input as well as Output.  An exception is when a pin is connected to the Global Input bus to route the signal to a digital block.  When a pin is connected to the Global Input bus, it cannot be configured in Pull up or Pull down modes.

REGISTERS

The GPIO pins are controlled by various registers.

Data Register: The state of a GPIO can be controlled / read by writing / reading the PRTxDR register.  For example to make P1[5] HIGH, Bit5 of PRT1DR should be set.  More about writing and reading GPIO pins in Part-2.

Drive Mode Registers:  There are three drive mode registers for each port that control the drive mode of the pins in a particular port.  These are the PRTxDM0, PRTxDM1 and PRTxDM2 registers. The combination of the bits of these three registers decide the drive mode of a particular pin.  For example, the drive mode of P2[3] will be decided the combination of Bit3 of PRT2DM0, PRT2DM1 and PRT2DM2 registers.  Details can be found in the Technical Reference Manual.

Global Select register: The PRTxGS register decides if a GPIO pin is under the control of the CPU or is connected to the Global In or Global Out bus.  When the bit in PRTxGS register is cleared, the pin can be controlled by the CPU by writing to the PRTxDR register.  When the bit in PRTxGS register is set, the pin is connected to the Global bus and connects to the internal hardware blocks.

Interrupt Control Registers: PRTxIE, PRTxIC0 and PRTxIC1 are registers that control the interrupt mode of a GPIO pin.

INTERRUPTS

Each GPIO pin may be configured to generate an interrupt on Rising Edge, Falling Edge or a Change from Read event.  The interrupt behavior of GPIO pins are controlled by the following registers.

PRTxIE Register: This register enables or disables the interrupt for a particular GPIO pin.  For example, if the interrupt has to be enabled on P1[5], Bit5 of PRT1IE register has to be set.  When the interrupt type is selected in the GPIO configuration pane in the PSoC Designer device editor, the designer automatically sets the PRTxIE register in the boot up code.

PRTxIC0 and PRTxIC1 Registers: These two registers are used in combination to choose between four options of interrupt type for each pin – Disabled, Rising Edge, Falling Edge and Change from Read.  Following are the bit combinations of PRTxIC0 and PRTxIC1 registers.  For example to configure P2[1] as a Rising Edge interrupt, Bit1 of PRT2IC0 should be cleared and Bit1 of PRT2IC1 should be set.  When the interrupt type is selected in the GPIO configuration pane in the PSoC Designer device editor, the designer automatically sets the PRTxIC0 and PRTxIC1 registers accordingly in the boot up code.

When the pin is configured for a Change From Read interrupt, an interrupt is generated whenever the state of the pin changes from the state that was read from the pin.  So, to generate an interrupt from both rising and falling edges, whenever an interrupt is generated from the pin, a read operation should be performed on the PRTxDR register.  Even if there is no requirement for such a read, a dummy read operation has to be performed for the interrupt to work.

INT_MSK0 Register:  Bit5 in the INT_MSK0 bit is the Mask bit for GPIO interrupt.  Only when this bit is set, the interrupts raised by GPIO pins will be processed by the CPU.  The device editor does not take care of setting this bit.  This bit has to be set in the firmware.

Notes:

  • Remember to enable the Global interrupts for the GPIO interrupt (or any other interrupts) to work.
  • If the drive mode is set to “HighZ Analog”, interrupt will not work.

PSOC DESIGNER – CONFIGURING A GPIO

All the GPIO pins can be configured using the GPIO configuration window in the PSoC Designer device editor.

 

Name: Giving meaningful names to the GPIO pins will make the project more readable.  For example, LED, SPI_MOSI, SPI_MISO, UART_TX etc.  Giving names to the GPIO also will be useful in controlling the pins using the register definitions in the psocgpioint.h file.  More about this later.

Select: This parameter selects the mode of the pin like Analog Input, Global Input, Global Output etc.  On specific pins, special functions like XTAL_IN, XTAL_OUT, I2C_SCL, I2C_SDA etc also will be available.  When the type of pin is selected, the drive mode will be automatically be set.

Drive:  This parameter selects one of 8 drive modes for the pin.  Though the drive mode will be automatically set according to the pin type selected in the previous parameter, it can be overridden.

Interrupt: This parameters sets the interrupt type of the pin

Continued in Part-2...

]]>
Tue, 01 Dec 2009 09:21:39 -0600
PSoC 1 GPIO Demystified - Part 2 http://www.cypress.com/?rID=39497 In Part-1 we looked at the features of the PSoC1 GPIO.  In this part, let us look at application scenarios.

WRITING TO A GPIO PIN

To control a GPIO using the CPU, first the GPIO pin should be set to StdCPU mode in the GPIO configuration window in device editor.  This will clear the corresponding bit in the PRTxGS register disconnecting the pin from the Global bus.  The drive mode should be set to any mode other than HighZ or HighZ Analog.  Now the pin may be controlled by writing to the PRTxDR register.  Following are some examples in assembly and C.

Assembly Examples:

or reg[PRT1DR], 0x02     ; Set P1[1]
and reg[PRT1DR], ~0x80   ; Clear P1[7]
xor reg[PRT0DR], 0x04    ; Toggle P0[2]

 

C Examples:

PRT1DR |= 0x02;     // Set P1[1]
PRT1DR &= ~0x80;    // Clear P1[7]
PRT0DR ^= 0x04;     // Toggle P0[2]


Notes:

  • M8C.inc file has the register definitions for assembly and m8c.h file has the register definitions for C.
  • While writing in assembly make sure that the Register bank is set to 0 before writing to the PRTxDR register.  Register bank may be set to 0 by using the M8C_SetBank0 macro
  • While using C, the compiler takes care of register bank switching.

However, this method has a disadvantage that it is not portable.  For example, let us say we have placed an LED on P0[5] and have used PRT0DR to control the LED.  Later in the design cycle of the project, the LED is to be moved to P1[2].  Now we will have to search all the locations in the project where PRT0DR is accessed and change this to PRT1DR.  Using Pin names will solve this problem.  Below is the procedure.

1.    Give a meaningful name to the pin to be controlled.  For example “LED”
2.    PSoC designer generates include files called psocgpioint.inc and psocgpioint.h, which has defines for the registers and masks for the pins.
3.    Include psocgpioint.inc or psocgpioint.h file in the C or assembly source file.  Now the pins can be controlled by using code like:

LED_Data_ADDR |= LED_MASK;  // C Code
or reg[LED_Data_ADDR], LED_MASK   ; Assembly code

Now, if the LED were to be moved to any other port, the register definition in the psocgpiont.inc and psocgpioint.h files will be automatically updated by the PSoC designer and there will be no need to change the application code.

READING A GPIO PIN

The state of a GPIO can be read by reading the PRTxDR register.  One important thing to bear in mind is that the PRTxDR register reflects the state of the GPIO pin, not the value that was written to the register.  For example, if you had written a 1 to a GPIO pin configured as a pull up and when reading the PRTxDR register, if the pin were shorted to GND externally, the value read from the PRTxDR will be 0, not 1.  This behavior gives rise to some interesting but unwanted situations which are explained in the next section on Read Modify Write operations.

Following are C and Assembly code examples to read from a GPIO pin.  Either the PRTxDR can be directly used or register and mask names from psocgpioint include files can be used.  In the below examples, an input pin named SWITCH is read.

Assembly Example:

mov A, reg[SWITCH_Data_ADDR]
and A, SWITCH_MASK
jnz PinHigh
; Pin state is Low
PinHigh:
   ; Pin state is high.

C Example:

if (SWITCH_Data_ADDR & SWITCH_MASK)
{
    // Pin is set.  Add code to process
}

Notes:

  • When a GPIO pin has to be configured as a digital input, set the drive mode to HighZ, not HighZ Analog.  As the Schmitt trigger section in the GPIO cell is disabled in the HighZ Analog mode, the state of the PRTxDR register bit corresponding to the pin will always be zero.
  • When a pin is configured for Pull Up mode, for example to read an external switch connected between the pin and GND, a 1 has to be written to the PRTxDR register bit to enable the pull up resistor.  Similarly, when a GPIO is configured in Pull Down mode, a 0 has to be written to the PRTxDR register bit.

READ MODIFY WRITE INSTRUCTIONS AND SHADOW REGISTERS

When you have input pins configured as Pull Up or Pull Down, and if there are other pins on the same port which are configured as output pins, an instruction that is used to update an output pin may accidentally set or clear the input pin thus latching the input.  For example let us consider the following scenario.

P1[0] - PullUP, Connected to a switch. 1 has been written to the bit in PRT1DR to enable the pullup
P1[1] - Strong, drives an LED.

Now, the following instruction is used to switch off the LED

and reg[PRT1DR],~0x02

The above instruction is a Read/Modify/Write instruction, ie, it first reads the pin states (not the value written to PRT1DR register before), does an “AND” operation with the mask and then writes back the result to PRT1DR register.  If the switch were pressed when this instruction is executed, the pin state of P1[0] would be 0, so the result of the operation would be

Pin State: x x x x x x x 0
AND operation: (x x x x x x x 0) & (11111101) = x x x x x x 0 0
Write back: x x x x x x 0 0

Bit-0 which drives the switch has been cleared in PRT1DR now and will never become high.  This will result in the input pin stuck to 0, irrespective of the state of the switch.

A workaround for this condition is using Port shadow registers. Declare a variable in RAM and initialize this variable in the beginning of code to the initial Port value. After this, do any Read/Modify/Write operation on this shadow register and then write the value of shadow register to the PRTxDR register.

// Declare a shadow register
BYTE Port1Shadow;
// Initialize in the beginning of code
// Bit0 is set to enable the Pullup for the key
Port1Shadow = 0x01;
PRT1DR = Port1Shadow;
// Now to clear the LED
Port1Shadow &= ~0x02;
PRT1DR = Port1Shadow;

WRITING A GPIO ISR

Now, let us configure a GPIO pin for interrupt and write an ISR that increments a variable “IntCount”.  In the Device Editor GPIO configuration, set the interrupt to the desired type.  The PSoC Designer will take care of the PRTxIE and PRTxICx registers in the boot.asm code

In main, enable the Global interrupt by using the M8C_EnableGInt macro

In main,enable the GPIO interrupt by using the below code.

M8C_EnableIntMask(INT_MSK0, INT_MSK0_GPIO);   // C code to enable GPIO interrupt
M8C_EnableIntMasm INT_MSK0, INT_MSK0_GPIO   ; Assembly code

Whenever a pin is enabled for interrupt in the PSoC Designer Device editor, the IDE generates a file called psocgpioint.asm.  This file has the place holder to write an ISR for the GPIO interrupt.  The following code should be added within the user code marker in the ISR function.

PSoC_GPIO_ISR:
    
   ;@PSoC_UserCode_BODY@ (Do not change this line.)
   ;---------------------------------------------------
   ; Insert your custom code below this banner
   ;---------------------------------------------------
   inc [IntCount]
   ;---------------------------------------------------
   ; Insert your custom code above this banner
   ;---------------------------------------------------
   ;@PSoC_UserCode_END@ (Do not change this line.)

   reti

If you would like to write the ISR in C, then do the following.

Declare the ISR function using #pragma interrupt_handler

#pragma interrupt_handler MyGpioISR

Write the interrupt handler function.

void MyGpioISR(void)
{
   IntCount++;
}

In the psocgpioint.asm file, place an ljmp instruction to branch to the C ISR

PSoC_GPIO_ISR:
    
   ;@PSoC_UserCode_BODY@ (Do not change this line.)
   ;---------------------------------------------------
   ; Insert your custom code below this banner
   ;---------------------------------------------------
   ljmp _MyGpioISR
   ;---------------------------------------------------
   ; Insert your custom code above this banner
   ;---------------------------------------------------
   ;@PSoC_UserCode_END@ (Do not change this line.)

   reti

More about C ISRs can be found in this KB Article

]]>
Sat, 28 Nov 2009 04:25:10 -0600
High Resolution Dithered DAC in PSoC 3 http://www.cypress.com/?rID=39285 A couple of weeks ago, I had written about a method to implement a High Resolution DAC using two 8 bit DACs.  Recently I had a very interesting discussion with one of my colleagues and a good friend, a young and brilliant guy named Kannan.  He showed me how to implement a high resolution Dithered DAC using a single 8 bit DAC, an 8 bit Mux, a couple of Control Registers and a PWM.  It is amazing what you can do with the PSoC 3 hardware.

Dithering is a widely used technique in Digital Processing where a noise is intentionally introduced into a system to increase the resolution of the system.  Say we have an 8 bit DAC with a full scale value of 255mV.  Each count of the DAC represents 1mV.  What if we wanted an output of 1.25mV from the DAC.  Switch the DAC output between 1mv and 2mV keeping the output at 2mV 25% of the time and 1mV 75% of the time, the average value of the output would be 1.25mV.  For an output of 1.5mV, the DAC output should be maintained at 2mV for 50% of the time and 1mV 50% of the time.


Now let us see how this method can be implemented using the PSoC 3 hardware to create a 10 bit DAC.

Place an 8 bit voltage DAC.  Select 1.020V (4mV / bit) as the range.  Set the Data_Source to “DAC Bus” and Strobe_Mode to “External”.  The output of the DAC can now be controlled using an 8 bit data bus and the output will be updated on the rising edge of the Strobe input.

Place a Multiplexer from the Digital >> Logic category.  Set number of input terminals to 2 and terminal width to 8.  The multiplexer can now switch between two 8 bit data buses.  Place two control registers from the Digital >> Registers category.  Set the number of outputs to 8.  Connect the 8 bit data bus of the Control registers to the input of the Multiplexer. 

Place a PWM, with a period of 3 and compare type set to “Less than”.  The output of the PWM now can be controlled to 0%, 25% and 75% duty cycle.  Connect the output of the PWM to the control input of the Mux.  Use the same clock of the PWM as a strobe to the DAC.  The hardware is now ready.

In firmware, write the Most Significant 8 bits of the 10 bit DAC value to the ControlRegister0 and one count higher value to ControlRegister1.  Use the Least Significant 2 bits to update the PWM’s pulse width.  Now, the PWM switches the input of the DAC between the two 8 bit Control Register values and the average output of the DAC would be our 10 bit DAC result.  Use an external Low Pass filter to remove the switching frequency.  As the switching frequency is at 125KHz, a simple RC filter will do the trick.  Below is the code.

void main()
{
   uint16 DacValue;
   VDAC8_Start();
   PwmMsb_Start();
   Amplifier_Start();
   for(;;)
   {
      DacMsbReg0_Write(DacValue >> 2);
      DacMsbReg1_Write((DacValue >> 2) + 1);
      PwmMsb_WriteCompare((uint8)(DacValue & 0x03));
   }
}

The range of the DAC now is 0 to 1020 counts; each count representing 1mV, subject to some offset and gain error inherent in the 8 bit DAC.

Quoting my brilliant friend “I bet this cannot be implemented with any other controller out there in the market!!”

 

]]>
Fri, 06 Nov 2009 10:35:58 -0600
PSoC 1 ADCs – The Five Golden Rules http://www.cypress.com/?rID=39197 Most if not all of the microcontroller designs that involve analog signal processing will require an ADC to convert an analog signal into a digital value that can be processed by the CPU.  PSoC 1 has a vast selection of ADCs that can be used depending on the application, ADCINC, ADCINCVR, ADCINC14, DELSIG8, DELSIG11, DelSig to name a few.  Most of the users, beginners to experts face some or other problem while using an ADC like ADC not completing the conversion, ADC result always zero, ADC result incorrect etc.  Below are Five Golden Rules that will help you to tame the PSoC 1 ™ ADC.

GLOBAL INTERRUPTS

A PSoC 1 ADC is a combination of analog and digital blocks and the CPU.  An SC block configured as a modulator converts the input analog signal into a digital bit stream.  A counter is used to count the time the bit stream is high for a given period of integration time.  A timer or a PWM is used to set the integration time.  At the end of integration cycle, the timer or PWM generates an interrupt and the processor reads the counter inside the interrupt. 


When Global Interrupt is disabled, the CPU will not respond to the timer’s (or PWM’s) interrupt to read the ADC result.  So, the ADC would never complete the conversion.  Any instruction, for example,

while(ADC_fIsDataAvailable() == 0);

that waits for the ADC result to complete will execute forever

Golden Rule No.1 – Always enable Global Interrupt

ANALOG POWER

The Analog power parameter under the Global Resources sets the power to the SC blocks and the reference. 

 

For the ADC to work correctly, always select the power settings “SC On / Ref Low”, “SC On / Ref Medium” or “SC On / Ref High”.  Selecting a reference with “SC Off” or “All Off” will result in the ADC not working.

The Reference power should be selected so that the Reference Generator is able to provide adequate power to the Analog blocks.  The power to the Reference section should always be equal to or greater than the highest power used by any analog block in the design.  For example, if you have a PGA and an ADC where the PGA operates at Low power and the ADC at Medium power, the Reference power should be set to SC On / Ref Medium or SC On / Ref High.

Golden Rule No.2 – Always provide power to SC Blocks and set appropriate Reference Power.

COLUMN CLOCK AND DATA CLOCK

The ADC has a parameter called “Clock”.  This selects the clock source to the Digital section of the ADC.  The column clock for the SC Block should be set to the same value as that of the “Clock” parameter.  In the picture below, the Clock parameter is set to VC2.  So, the Analog Column clock should also be set to VC2.  If the Column clock and Data clock are not the same, the output of the ADC will not be correct.

Golden Rule-3: The Data Clock and Column Clock should always be equal

CLOCK PHASE

The output of Switch Capacitor blocks is not a continuous signal.  SC blocks have two phases of operation.  Phase-1 is the charge acquisition phase when the input signal is sampled.  During this phase, the output of the SC block is 0.  Phase-2 is the charge transfer phase when the acquired charge is transferred to the output and the output is proportional to the ratio of input and output switch capacitor cell values.  So, the output of the SC block is valid only during Phase-2.  Application Note “AN2041 - Understanding Switched Capacitor Blocks” is a very good source of information on this subject.

If an ADC’s input is connected to the output of another SC Block, say a 3 Op-Amp Instrumentation Amplifier or a Filter, the output of this source SC block is 0 during Phase-1 of the SC Block operation.  The ADC modulator which is also an SC Block samples the input signal on Phase-1. Because of this, the ADC will always see 0V at its input and will always produce an output of 0.  Under this circumstance, the ClockPhase parameter of the ADC should be set to “Swapped”.  Now, the ADC modulator will sample its input on Phase-2 of the SC Block cycle when the input is valid.  This will produce the correct ADC result.  If the input to the ADC is a continuous signal from a CT block, the Analog bus or a direct pin, then the ClockPhase parameter can be set to either “Normal” or “Swapped”

Golden Rule-4: Always set the correct value for the ClockPhase parameter

WAITING FOR THE RESULT INSIDE AN ISR

Many a time, you may want to initiate an ADC conversion inside the ISR of another user module, say a timer or counter and process the output of the ADC inside the ISR.  The code may look like this:

void TimerISR (void)  // This is an ISR
{
    int Result;
    ADC_GetSamples(1);
    while(ADC_fIsDataAvailable() == 0;
    Result = ADC_iGetDataClearFlag();
}

The above code will result in the program stuck in the while loop waiting for the ADC result to be available.

When an ISR is entered, the Global Interrupt is disabled and is enabled only when the ISR exits.  So, inside an ISR no other interrupts will be serviced.  The ADC requires the interrupt to work for its conversion to be completed.  As the ADC interrupts will not be serviced inside the TimerISR, the ADC conversion would never complete.  Re-enabling Global interrupt inside the ISR would be a solution.  But this is not preferable as this could also result in nested interrupts locking the CPU inside ISRs forever.

So, do not wait for an ADC result to be available inside another ISR.  Instead set some flag inside the ISR and do the ADC conversion in the foreground.

Golden Rule-5: Never wait for the ADC result inside an ISR

Follow the above five Golden Rules and see the PSoC 1 ADCs work happily for you!!

]]>
Sun, 25 Oct 2009 21:30:34 -0600
High Resolution DAC in PSoC3 http://www.cypress.com/?rID=38989 PSoC3 has 8 bit voltage and current DACs.  Higher resolution DACs may be created by combining two 8 bit DACs, one for MSB and one for LSB and summing their outputs together.  The DAC section of the TRM shows how to chain two 8 bit DACs to get a 12 bit DAC.

The MSB is implemented using an 8 bit DAC configured for 2.040mA full scale.  Each bit of the MSB DAC now corresponds to 8uA.  To create a 12 bit DAC, we need to extend the resolution by four bits and each bit should be equal to 1/16 of the MSB DAC, which is 0.5uA.   This can be implemented by using Bits 2 to 5 of another 8 bit DAC configured for a 32uA output.  The schematic diagram of a PSoC3 project to create a high resolution current DAC is shown below.


Below is the code that is used to split the 12 bit DAC value and update the MSB and LSB DACs.

DAC_MSB_SetRange(DAC_MSB_RANGE_2mA);
DAC_LSB_SetRange(DAC_LSB_RANGE_32uA);
DAC_MSB_Start();
DAC_LSB_Start);
DacValue = 4095;
DAC_MSB_SetValue((DacValue >> 4) & 0xFF);
DAC_LSB_SetValue((DacValue << 2) & 0x3C);

To implement a 10 bit DAC, the code would be:

DAC_MSB_SetRange(DAC_MSB_RANGE_2mA);
DAC_LSB_SetRange(DAC_LSB_RANGE_32uA);
DAC_MSB_Start();
DAC_LSB_Start);
DacValue = 1023;
DAC_MSB_SetValue((DacValue >> 2) & 0xFF);
DAC_LSB_SetValue((DacValue << 4) & 0x30);


But this method also has its disadvantages.  Any mismatch in gain between the MSB and LSB DACs will result in non-linearity and unequal step sizes.  This can be compensated by calibration, either by trimming the DAC using the DACx_TR register or by using the unused least significant bits of the LSB DAC.  Stay tuned!!

]]>
Mon, 12 Oct 2009 23:55:09 -0600
Writing to a PSoC3 GPIO – Various options http://www.cypress.com/?rID=38854 Any microcontroller project will have the need to control a GPIO pin using a CPU.  Applications could be simple ones like switching On/Off an LED, a relay, a buzzer etc to complex ones like generating a software PWM, bit-banging I2C protocol etc.

There are many options to control a PSoC3 GPIO in firmware.  Let us take a look at some of these options and their pros and cons.

Option-1: Use Port in APIs

When a Digital Output Port component is placed in the project, the PSoC Creator generates API functions to control the port pin.  The function used to write to the pin is <Pin Name>_Write.  For example, for a Port Pin component named Out1,

Out1_Write(1);   // Set the pin
Out1_Write(0);  // Clear the pin

Pros: The advantage of using the API function is the ease of programming and portability.

Cons: The disadvantage of using this method is the high number of processor cycles taken to update the pin.    Following is the listing of the Output1_Write function.
; void Out1_Write(uint8 value)

    RSEG  ?PR?_Out1_Write?OUT1
_Out1_Write:
    USING    0
            ; SOURCE LINE # 34
    MOV      DPTR,#value?040
    MOV      A,R7
    MOVX     @DPTR,A
; {
            ; SOURCE LINE # 35
;     uint8 staticBits = Out1_DR & ~Out1_MASK;
            ; SOURCE LINE # 36
    MOV      DPTR,#05100H
    MOVX     A,@DPTR
    MOV      R7,A
    MOV      A,R7
    ANL      A,#0EFH
    MOV      R7,A
    MOV      DPTR,#staticBits?041
    MOV      A,R7
    MOVX     @DPTR,A
;     Out1_DR = staticBits | ((value << Out1_SHIFT) & Out1_MASK);
            ; SOURCE LINE # 37
    MOV      DPTR,#value?040
    MOVX     A,@DPTR
    MOV      R7,A
    MOV      A,R7
    SWAP     A
    ANL      A,#0F0H
    MOV      R7,A
    MOV      A,R7
    ANL      A,#010H
    MOV      R7,A
    MOV      DPTR,#staticBits?041
    MOVX     A,@DPTR
    MOV      R6,A
    MOV      A,R7
    ORL      A,R6
    MOV      R7,A
    MOV      DPTR,#05100H
    MOV      A,R7
    MOVX     @DPTR,A
; }
            ; SOURCE LINE # 38
?C0001:
    RET     

The above code takes 58 CPU cycles including the call and return.

Option-2: Use Port Data Register and Mask

In this method, the port data register is accessed in the external data memory space using the PHUB.   For every Port Pin placed in the schematic, a header file <Pin Name>.h has the declarations for the Port data register and the mask.  For a Port Pin named Out1, the Port data register and the mask are Out1_DR Out1_MASK respectively.  For example:

Out1_DR |= Out1_MASK;  // Set the pin
Out1_DR &= ~Out1_MASK; // Clear the pin

Pros: This type of access takes less processor cycles than the API function call.  The example code #1 above results in the below compiled code.

;         Out1_DR |= Out1_MASK;

            ; SOURCE LINE # 41
    MOV      DPTR,#05100H
    MOVX     A,@DPTR
    MOV      R7,A
    MOV      A,R7
    ORL      A,#010H
    MOV      R7,A
    MOV      A,R7
    MOVX     @DPTR,A

This takes 13 CPU cycles, about 4 times faster than the Port pin API function call.

Cons: There isn’t any great disadvantage of using this method other than the fact that this method is still slower than Option-3 below, and sacrifices some amount of readability compared to Option-1.

Option-3: Control the pin using the SFR register space

In this method, the port data register is accessed directly in the SFR register space.  There are two SFRs that need to be controlled.

SFRPRTxDR: The register bits control the bits of the corresponding port.  For example the value in Bit5 of SFRPRT0DR register controls the state of P0[5].

SFRPRTxSEL: Setting the corresponding bit in this register, enables the control of the port pin through the SFRPRTxDR register.  For example, if Bit5 of SFRPRT0SEL is set, then the state of P0[5] is controlled by the value of Bit5 of SFRPRT0DR register.  If the bit is cleared, the port can be controlled only through the PHUB interface.

These registers are declared in PSoC3_8051.h header file under the cy_boot folder in the workspace explorer.  Details of these registers may be found in PSoC3 Technical Reference Manual under Section 4.6.4 – I/O Port Access SFRs.

For example, to switch On/Off P1[5]

// First enable SFR access for P1[5].  This has to be done only once in the beginning of code
SFRPRT1SEL |= 0x20;

// To switch on
SFRPRT1DR |= 0x20;

// To switch off
SFRPRT1DR &= ~0x20;

// To toggle
SFRPRT1DR ^= 0x20;

Pros: This is the fastest way to modify the port pin state.  This takes  a single direct memory access instruction and takes 3 CPU cycles to execute.

Cons: Not portable.  If you relocate a Port Pin component in the schematic to a different GPIO port, then all the code that access the pin through SFRs have to be rewritten.

Summary:

1. If the project does not have any timing restrictions and you prefer readability over execution time, use Option-1
2. If you are working on time critical application where every processor cycle counts, and readability or portability is not important, use Option-3.
3. Option-2 is the ideal solution where it has 4x speed over Option-1 and does not sacrifice portability.

]]>
Mon, 05 Oct 2009 12:25:19 -0600
E2PROM User Module - Usage Notes http://www.cypress.com/?rID=38632 The E2PROM user module is a very handy user module for emulating an E2PROM in the Flash program memory.  Here are some key points to remember while using the E2PROM user module. 

My apologies for the very long article.  Wanted to keep it short, but as I kept adding information this grew into a 1000+ word blo(n)g. 

 

User Module Parameters:

Starting Block: This specifies the flash block number where the E2PROM begins.  Always place the E2PROM in the last blocks of the flash.  For example, in a 32K device, a 256 byte (4 blocks) E2PROM should be placed in blocks 508 to 511.  So, the first block should be 508.  This ensures that maximum space is available for the code memory and prevents clash between code memory and E2PROM.

Remember to modify the flashsecurity.txt file and set the protection level of the flash blocks to “U” or “R”

w  w  w  w  w   w   w   w   w   w   w   w   w   w   w   w ;    Base Address 7800
w  w  w  w  w   w   w   w   w   w   w   w   u   u   u   u ;    Base Address 7C00
; End 32K parts

Length: This parameter sets the size of the E2PROM in bytes.  For the above example, the length parameter would be 256.

E2PROM Write Function:

To write data to the E2PROM, use the E2PROM_bE2Write function.  The prototype of the function is

char E2PROM_bE2Write(WORD wAddr, BYTE *pbData, WORD wByteCount, char Temperature);

wAddr: This is the location in the E2PROM where you would like to write the data.  A very common mistake made is people enter the physical address of the flash location.  The value should be relative location in the E2PROM, not in flash.  For the example mentioned above, to write data to the first location in the E2PROM, the value of wAddr should be 0x0000, not 0x7F00.

*pbData: This is the pointer to the buffer that holds the data you want to write to the E2PROM.  If the data is not in a char buffer, then you use typecasting.  For example, if to write a structure MyStruct, typecast the pointer to (char*)&MyStruct.

wByteCount: This is the number of bytes to be written to the E2PROM.  More about it later.

Temperature: The Temperature parameter is used by the E2PROM API to calculate the flash write pulse width.  At higher temperatures the flash has to be written with a smaller pulse width and at lower temperatures with a longer pulse width.  The flash will meet its maximum endurance and write cycles if it is written with the correct pulse width.  If the device is going to operate within a temperature range of 0 to 50 degrees, it is ok to pass the value of 25 for temperature.  But for operation over the full temperature range, use FlashTemp user module and pass the correct die temperature.  If this is not done, either the data retention or the flash endurance will be compromised.  If the temperature value passed is less than the operating temperature, the flash will be written with a longer pulse width than required.  This will reduce the flash endurance.  On the other hand, if the temperature value passed is higher than the operating temperature, the flash will be written with a lower pulse width than required.  While this does not affect the endurance, the data retention will be less than the guaranteed 10 years. 

 

The bE2Write function returns the status of the write operation.  A return value of 0x00 means the write was successful.  -1 means error in writing which could be because the flash is write protected. -2 means stack overflow.  Always check the return value in your program to make sure that the write was successful.

Full Block Write vs. Partial Write

E2PROM writes always take place in 64 byte blocks.  When you write less than 64 bytes of data, it is called a partial write.  The flash write API first reads all the 64 bytes from the flash block into RAM, modifies the desired bytes and writes back the 64 bytes of data to Flash.  This results in a heavy RAM overhead requiring 103 bytes of stack space, whereas a full block write takes only 32 bytes of stack.  In devices with only one RAM page, the global variables and stack share the 256 bytes.  If the RAM usage of the globals is high, this could lead to stack overflow errors while performing partial writes.  Under such condition, it is always advisable to perform a 64 byte write.  Even if you are writing say 10 bytes of data, set the ByteCount to 64.  The first 10 bytes will be the actual data followed by data from subsequent RAM locations.  Check out the E2PROM user module data sheet under the section “Efficient Memory Usage” for more details.

 

Initializing the E2PROM with data:

Many a times you may be using the E2PROM to store calibration data or any other system related data, where you would like to load the E2PROM with some initial values while the device is programmed.  Following method may be used to achieve this.

In C: Use the “#pragma abs_address” directive.  For example, if the E2PROM is placed in the last flash block in a 32K device, and if you wanted to initialize the first 10 bytes with some value:

 

#pragma abs_address 0x7FC0
const char InitialValues[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
#pragma end_abs_address

In assembly:

area eeprom(rom, abs)
org 0x7FC0
db 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09

 

A Practical Situation – Storing and Retrieving a Structure

Let us take a look at a practical E2PROM usage where a calibration structure is stored, read and written in the E2PROM.

Create a typedef for the structure 

 

typedef struct CAL_STRUCT
{
    int Offset;
    float Scale;
}CAL_STRUCT;

RAM variable to store the calibration values 

 

CAL_STRUCT CalValuesRam;

Initialize the E2PROM with initial values: 

 

#pragma abs_address 0x7FC0
const CAL_STRUCT CalValuesEeprom = {
0x0023,    // Initial value for offset
2.5456   // Initial value for scale
};

Now to read the value from the E2PROM to the RAM you can use either the E2PROM_Read function:

 

E2PROM_E2Read(0x0000, char* &CalValuesRam, sizeof(CalValuesRam));

Or:

 

CalValuesRam = CalValuesEeprom;

To write the values from the RAM to E2PROM

E2PROM_bE2Write(0x0000,(char*)&CalValuesRam, 64, 25);

]]>
Tue, 22 Sep 2009 14:08:18 -0600
PSoC3 and PSoC5 are here http://www.cypress.com/?rID=38455 At last, after a long wait and lots of suspense, PSoC3 and PSoC5 have been officially announced.  I sat down to do my first project, measure an analog input signal with an ADC, pass the result through an FIR filter, convert to voltage and display on the LCD.  Or should I call this is my pseudo first project as I have been in some of the PSoC3 training sessions and had worked with some very early versions of the PSoC Creator.

The download and installation of the PSoC Programmer and PSoC Creator went quite smooth without a hitch.  But for some reason, the registration happened only after a few retries and “Invalid user name and password” errors. 

Working with the PSoC Creator is fun.  The Creator looks like a hybrid of PSoC Designer and OrCAD.  In PSoC Designer, you place user modules in the correct analog/digital blocks, use the Analog / Digital interconnect nets to connect between blocks and pins etc. In the Creator, you draw a schematic instead.

You place the required resources, connect them using wires, and configure the pin outs in the pin configuration window.  Voila, the device is ready.  Writing code is similar to PSoC Designer where you use the Library API of the components - the user modules of PSoC Creator.  If you have worked with PSoC Designer, it should be quite easy to learn PSoC Creator.  Once I had the schematic and the pin configurations done, writing code was quite simple and I was able to get the project working in less than 20 minutes.

Overall, my pseudo-first experience with the PSoC Creator was great.  I relived the thrill of working with PSoC Designer version 1.31, back in 2002.  There is so much to explore - New IDE, new processor cores, new compiler, new debugger…  I am loving it.

Hello World.  PSoC3, PSoC5 and the Creator are here and are here to stay!!!

]]>
Fri, 18 Sep 2009 12:19:59 -0600
Wrong ADC values while debugging http://www.cypress.com/?rID=38535 This is one of the most common problems users face with an ADC while debugging.  The ADC result is always corrupt after you hit a breakpoint in the program.  Why does this happen?

Let us take a look at how an ADC is created in a PSoC.  Except for the SAR6 ADC, which uses a single Analog block, all other PSoC ADCs (ADCINC, ADCINCVR, DelSig, DELSIG8/11 etc) are a combination of Analog and Digital blocks.  The block diagram of an ADCINC12 is shown below.

An SC Bloc configured as an analog modulator converts the input analog signal into a digital bit stream, whose On Time / Off Time ratio is proportional to the input signal.

0V - 50% on, 50% off
+Vref/2 - 75% on, 25% off
-Vref/2 - 25% on, 75% off
…and so on.

A counter integrates this bit stream for a fixed integration window set by a timer, and at the end of the integration cycle, the CPU reads the value in the Counter which is the ADC result.  The hardware implementation of the digital integrator is different in different ADCs, but the concept is the same.  For the ADC result to be correct, the CPU has to read the value from the counter exactly at the end of the integration cycle.  If it fails to do so, the counter will continue counting the bit stream and will result in an incorrect ADC result. 

When a break point is hit while debugging, the CPU halts.  But the analog and digital blocks continue to run in the background and the counter would be counting many ADC integration cycles.  So, naturally when CPU resumes execution after the breakpoint, the value read from the counter would be wrong.  If you are debugging some other section of the program that does not have any dependency on the ADC result, then just ignore this.  When you program the device and the program runs continuously, the ADC result would be correct.  If you are debugging a section that depends on the accuracy of the ADC result, then here are some things that you can do.

1.    As the program is running, dynamically set a breakpoint after the instruction that reads the ADC result, by left clicking on the left margin of the code window (left side of the Line number).  When the program halts, the value read from the ADC would be correct.  Now clear the breakpoint, run the program and dynamically place the breakpoint again.

2.    Use the following code.

      for(i=0; i<2; i++)
      {
         while(ADC_fIsDataAvailable() == 0);
         ADCResult = ADC_iGetData();
         ADC_ClearFlag();
      }
      asm("nop");  ---> Place breakpoint here

In the above code, the “for” loop runs two cycles.  The ADC result read during the first iteration of the for loop is corrupt. The second ADC result is clean.  So, when the break point is hit, the ADC result will always be correct.  Remember, when using a Delta sigma ADC, the for loop should be written for 3 cycles, so that the first 2 results are dropped.  For other incremental ADCs, dropping one result is enough.

3.    Instead of running the ADC in continuous sampling mode, run it in single sample mode.

      ADC_GetSamples(1);
      while(ADC_fIsDataAvailable() == 0);
      ADCResult = ADC_iGetDataClearFlag();
      asm("nop");  --------------------------> Break point here

When the ADC is run in single sample mode, the ADC conversion starts when the "ADC_GetSamples" function is called.  On end of conversion, the counter and timer are stopped.  They will be started only when the ADC_GetSamples function is called.  Thus, the ADC result would never be corrupt.  This applies only to incremental ADCs and can not be used for Delta sigma ADCs.

Happy debugging!!

]]>
Fri, 18 Sep 2009 12:19:29 -0600
All ye lovely birds http://www.cypress.com/?rID=38389 One another passion I have other than PSoC is bird watching and photography.  I enjoy trekking into jungles or waterbodies during week ends with my Canon DSLR camera and 300mm telephoto lens and shoot birds (with my camera ofcourse).  It is a great experience seeing all those colorful birds in their natural habitat and is a great stress buster.  Here are some photos from my collection.

Spot Billed Pelican in Flight - Shot at Karaji lake,Mysore, Karnataka, India, a waterbody thousands of migratory birds come from all over the world every year.  It took 1/2 an hour and 10's of shots to ge this perfect photo of the majestic bird in flight.  Due to dwindling habitat of water bodies, this bird is now classified as "Near Threatened"

Australian Ibis - Resting after flight - Shot at Karanji Lake, Mysore

Yellow billed babbler - This is a very noisy bird and is always found in groups of 7 to 10.  Also called as 7 sisters.  When I was showing this photo to my boss, he observed that the bark that the bird is sitting looks like a snake's head.

Rose Ringed Parakeet - I shot this in Birla Institute of Technology in Pilani Rajasthan which I had visited to conduct a PSoC workshop.  This bird patiently posed for me till I got the perfect shot.

Red Wattled Lapwing - Shot at Birla Institute of Technology, Pilani.  This bird which is considered to be very shy always tries to keep distance from human beings.  But surprisingly, this bird came quiet close so that I could get a very clear shot.

Send me your comments to graa@cypress.com.

]]>
Tue, 15 Sep 2009 20:32:15 -0600
Let’s Talk PSoC... http://www.cypress.com/?rID=38347 Hi Everybody,

I am M. Ganesh Raaja and I work for Cypress Semiconductor as a Principal Applications Engineer.  I completed my Diploma in Electronics and Communications Engineering in 1992 and since then have worked in various jobs like servicing computer peripherals (huge floppy drives, huge hard disks, huge line printers etc), design engineer in a power electronics company designing UPS, design engineer in an Instrumentation company designing industrial sensors and having my own company developing custom industrial automation products using 8051 controllers. 

In 2002, I came across PSoC when searching for a microcontroller for an advanced panel meter design.  You could call it love at first sight.  Though that panel meter design never went through, it completely changed my life and brought me and PSoC together.  I bought the CY3205 development kit with the ICE-4000 emulator and started playing around with PSoC.  Since then I have been addicted to this device and have been doing various PSoC related things like writing application notes, conducting PSoC seminars for customers, writing user module code, training engineers on PSoC etc.  Another addiction I have is posting regularly in PSoC Developer forums as “graaja”.  In the past 6 months though, my activity there has reduced due to various reasons, which I plan to restart soon.

In this blog I would like to share with you many of my experiences with PSoC, tips and tricks of using PSoC, interesting articles I come across on PSoC and microcontrollers in general etc.

Welcome.  Let’s Talk PSoC!!

]]>
Fri, 04 Sep 2009 14:32:54 -0600