Continuing on the PSoC4. I’ve written the previously discussed register-poking-code into some functions for the library. This code talks nicely over the UART, as it did before. So, now the code is in the library for the 4100/4200 family, let’s have a look at the 4100M/4200M family. As far as I can tell, the only thing that differs is the timing part.

The 4100M/4200M family does not have this cascading structure we saw in the 4100/4200 family. Instead there are just a number of integer divisors and a number of fractional divisors. The peripheral clock divisors are called PERI in this family. It contains 16 integer divisors (16 bit) and 4 fractional divisors (16.5 bit). You just write the desired value to the corresponding fields in the registers. For the fractional divisors, the fraction is (int_part + frac_part / 32). I hadn’t figured out this part last time, but it is described in the 4200M Architecture TRM.

Then there are the control registers, which associate one of the previously discussed divisors to a peripheral. This seems quite simular to the way it was on the 4200, but there is one difference. On the 4200M we also have a command register, and with writes to this register we can enable and disable divisors. Furthermore, we can configure alignment of clocks using this register.

When implementing the PERI peripheral as described above, surely, the UART did output its data as it did before on the 4200 family. So far so good, let’s more on to the timer (Timer, Counter, PWM: “TCPWM”). Just poking around in the registers for now. By the looks of it, despite being at different addresses, the registers look the same on both families. So, let’s play a bit. I’ll create a down-counting timer, that counts from 1000 down to 0. I want to connect this timer to an output, and toggle the output on underflow. I’ve connected LEDs to the TCPWM0 outputs (Pin 2.4 and 2.5) and when running the following code, they alternate 1 times per second.

        // Configure a clock for the TCPWM0: 24000000/24000=1000, so a 1 kHZ clock
	pclk_set_divider(1,2,24000);
	pclk_select(PCLK_SELECT_TCPWM0,1,2);

	TCPWM_CNT_TR_CTRL2(TCPWM_CNT0_BASE) = 2 << 4; // toggle pin on underflow
	TCPWM_CNT_PERIOD(TCPWM_CNT0_BASE) = 1000; // set period. 1 sec
	TCPWM_CNT_CTRL(TCPWM_CNT0_BASE) = (0 << 24) | (1 << 16) | (1<<1); //Timer, Down, auto-reload period

	// Pin 2.4 and 2.5 are for TCPWM0  2.4 is normal, 2.5 is inveted.
	hsiom_set_function(HSIOM_PORT2_BASE, 4, HSIOM_PORT_SEL_ACT_0);
	hsiom_set_function(HSIOM_PORT2_BASE, 5, HSIOM_PORT_SEL_ACT_0);

	// Configure the pin as push-pull output
	gpio_set_mode(GPIO_PORT_2_BASE,GPIO_DM_0_1, 0b110000);

	TCPWM_CTRL = 1; // enable timer 0
	TCPWM_CMD = 1 << 24; // start counter for timer 0

	while(1);; // do nothing, the timer should act on its own 

So far so good, I've got initial results with the timer. It seems I'm on the way. I'll have to look at the other configurations for this peripheral, but first, let's try to run this code on the 4200M too. So I replaced the clock setup code with the code I've written for the 4200M series. This set-up code should work as I've got output from the UART.

	//pclk_set_divider(1,2,24000);
	//pclk_select(PCLK_SELECT_TCPWM0,1,2);

	peri_divider_disable(0, PERI_PCLK_SEL_TYPE_INTEGER_16);
	peri_integer_divider_set_divisor_16(PERI_DIV_16_CTL0, 24000);
	peri_select_clock_peripheral(PERI_PCLK_CTL11, 0, PERI_PCLK_SEL_TYPE_INTEGER_16);
	peri_divider_enable(0, PERI_PCLK_SEL_TYPE_INTEGER_16);

I've connected LEDs to the board again, and I ran the code, but no LEDs blink. When I look at the debugger, I see the value in the COUNTER register of the timer change, so the timer appears to be running. So, I'm not really sure what is wrong here. As the HSIOM and GPIO code I'm using worked for the UART, and I haven't spotted any differences in these peripherals yet. According to the datasheets, the output pins for the first timer are also the same. So, I'm not really sure what's happening here yet.

Update 1: Been looking at those registers in the 4200M TRM. They appear to be exactly the same. One note in the datasheet, it seems the 2.4/2.5 pins are marked tcpwm.line[0]:1/tcpwm.line_compl[0]:1, seeing 3.0/3.1 marked tcpwm.line[0]:0/tcpwm.line_compl[0]:0. However switching to those pins doesn’t make a difference. So, I’m not sure what the deal is on the 4200M. I guess, I better just focus on the 4200 for now.

Update 2: I've added an interrupt to the underflow event, which works fine on both micros, so the timer works fine.

TCPWM_CNT_INTR_MASK(TCPWM_CNT0_BASE) = 1; // enable TC interrupt
void dsi16_tcpwm0_isr(void){
	TCPWM_CNT_INTR(TCPWM_CNT0_BASE) = TCPWM_CNT_INTR(TCPWM_CNT0_BASE); // Clear interrupt flag
	gpio_toggle(GPIO_PORT_1, 1<<6); // Toggle led
}

On the 4200M it is void dsi19_tcpwm0_isr(void), just a different IRQ number, but the rest is the same. This DSI stuff is still something I need to look at.