The PSoC devices offer varying amounts of programmable analog and programmable digital fabric and memory. Members of the PSoC 1 family also include Cypress's proprietary 8-bit M8C processor core; members of the PSoC 3 family include an 8-bit 8051 core; members of the PSoC 4 family include a 32-bit ARM Cortex-M0 core; and members of the PSoC 5 family boast a 32-bit ARM Cortex-M3 core.

For my current project, I decided that a PSoC 4 would be able to offer all the capabilities and functions I require. With the aid of the PSoC 4 Pioneer Kit (Arduino shield compatible), I quickly established that the PSoC 4200 would meet my needs. Since this project was a rush job, I quickly committed to a PCB so that it could be produced in parallel with the rest of the development.

For maximum configurability, PSoC devices contain reconfigurable logic blocks called Universal Digital Blocks (UDBs). The PSoC 5 has up to 24 of these UDBs while the PSoC 4200 has 4 (the PSoC 4100 has none). In the PSoC 4, some of these UDBs are replaced with components that are not as configurable. In some cases, the I/O pins are proscribed, nudging this approach closer to a normal microcontroller. When comparing the PSoC 4 to the PSoC 5, in addition to the differences between the ARM Cortex M0 and M3, there are also differences with regards to the clock frequency, Flash, SRAM, and the speed of the peripherals like the ADC (analog-to-digital converter).

As a starting point for my project, I required a two-channel ADC. You can see its placement on the device schematic in Figure 1.

Figure 1. The ADC component has been placed and the input pins named and attached. Part of the configuration of the ADC options is shown here.(Click here to see a larger image.)

My initial thought was that the IP block for the ADC on the PSoC 4 would be nominally the same as on the PSoC 5 (which I used for a previous project), but this was not the case. Cypress has rethought this and created the ADC block with quite a few nice touches. Even though there is only one ADC, it can be configured with up to four differential channels that will automatically sequence through their conversions (you can set delays on each conversion). Furthermore, you can build in averaging automatically, thereby saving you writing the code. Other IP components in the device show a similar flair.

In order to drive my bi-colored LEDs (as discussed in my previous blog) I needed a PWM controller, but I wanted to use a single PWM for both the red and green since I wasn't varying the shade of orange. I added a few logic gates as illustrated in Figure 2, and I had the functionality that I was looking for. You can't do that on many micros!

Figure 2. The output of the PWM is conditioned by the addition of two AND gates and a control register so that I can have blank, red, green, or orange, with the brightness being controlled by the PWM ratio. The second bi-color LED has another PWM controller configured in exactly the same way.(Click here to see a larger image.)

After I had realized this approach, I was looking at the different components (in the form of IP configurations) and came across a device called a PrISM (Precision Illumination Signal Modulation) which had two PWM outputs and the ability to independently control them, which is pretty much had what I had set up. It also has a pseudo random PWM variation to reduce EMI noise. Unfortunately, this is where I bumped into having laid out the PCB beforehand. There weren't enough resources to allow me to use the PriSM and the SPI controller and some other components that I had selected. If I had laid out the PCB for the fixed output pin version of the SPI, everything would have been fine. It would have been nice to use the PrISM, but not using it wasn't a show-stopper.

I expect changing from debug to release to change optimizations, although it should be overridable (some compilers are weak here). Debugging optimized code is almost impossible, as some variables exist only in registers, common code elements are re-used and the physical ordering of instructions may not resemble the source code ordering. The bottom line is that debugging optimized code involves at a minimum frequent unexpected bouncing around in the source.

As previously stated, volatile is a useful keyword. It is also used for variables that may be changed by an interrupt.

However, the clean way to do timed stuff is with a timer. In its simplest form, set a hardware timer to some useful rate (generally between 1 us and 1 ms) and read it repeatedly until sufficent counts elapse. A software tick timer updating a volatile variable is another (and more common) way to do the same thing, particulalry if the time interval required is in the ms range rather than us. The more elegant approach for ms scale delays is to capture a start value and then go do something else, while checking back periodically to see if the interval has elapsed. If precision is required, when the interval is nearly over it can hang in a loop for the last few counts. Of course with the rich timer resources of the PSoc, a dedicated hardware timer and some logic is an even better alternative. (BTW the major league part in this game is the Zynq, which has two A9 cores and about 100,000 gates of logic.)

I just found out about the $4 4200 proto kit a week or so and order half a dozen, four of which will soon be part of a project I have been meaning to do for several years. I haven't plugged one in, yet, but am looking forward to it. If I understand it right, the 4200 can implement six UARTS in hardware (two fixed and four as digital blocks--one is required for downloading and debugging). Twelve bit ADC is a luxury for this type of chip, too, not to mention 32 bit RISC core, even if it is only M0.

Yeah the interrupt bug can be quite annoying, I ran into it several times.

If the interrupt isn't quite as critical for what you want to debug, you can disable breakpoints while debugging in Creator(I remember a little lightning symbol which can disable all global interrupts). Not an elegant solution but can work sometimes.

Moving some of my hobby stuff from PSoC5 to PSoC4 felt like quite a step back for me though. You get so used to any pin anywhere you forget that PSoC4 has a quite a few fixed function pins as well. For the sweet price point though, its well worth the sacrifice.

Do I need to buy a Keil license in order to work with the PSoC 4 device or everything I need is included in the Cypress toolchain?

No you don't have to buy anything. I think there is an option which will improve code density or something like that, but so far I haven't bumped into any limitations (and I have used it on the PSoC5 as well). However you do have to register with Keil.

which tells the compiler not to optimize loads and stores to that variable. "volatile" is mostly used to identify a variable as memory-mapped I/O, which means it could change value any time, e.g., if it's the current value of GPIO pins. Writes to a volatile variable may have side-effects like shifting data out though a UART pin. "volatile" is also used for variables that are shared with interrupt service routines or other tasks

Thanks for pointing this out. However, it seems to me that I adopted a rather poor and even inelegant method of creating code usage. It would have been better of me to adopt the use of assembly instructions like asm ("nop");

which tells the compiler not to optimize loads and stores to that variable. "volatile" is mostly used to identify a variable as memory-mapped I/O, which means it could change value any time, e.g., if it's the current value of GPIO pins. Writes to a volatile variable may have side-effects like shifting data out though a UART pin. "volatile" is also used for variables that are shared with interrupt service routines or other tasks.