problems with timer and gpio interrupts (project attached)

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

I'm trying to develop a system in which input data is decoded. The input waveform to be decoded is a spi byte from an external device with spi frequency of 100KHz this is connected to p1_3

   

The timer 16 is set to run at 1MHz with a period of 10, so that the terminal count occurs every 10us.                                     P1_3 is set to generate an interrupt on every falling edge of the waveform

   

On the first falling edge the timer is started, on every subsequent falling edge the value newdip is updated. In the timer_isr, the program should check if there's been a gpio interrupt in the past 10us if not, the variable value[] is updated.

   

I tried running the program with only the gpio and only the timer16 and they work fine individually but I can't get them working together. I observed that only the gpio_isr is called not the timer_isr

   

Please can anyone help me? I've been stuck on this problem for a week now and still no solution. THANKS

0 Likes
1 Solution
Anonymous
Not applicable

Hi,

   

Why don't you use the SPIS user module? You would just have to connect the CLK, the MISO and the SS pin to your MCU.

   

Then you would use the example code provided in the user module datasheet.

View solution in original post

0 Likes
21 Replies
Anonymous
Not applicable

Hi,

   

Why don't you use the SPIS user module? You would just have to connect the CLK, the MISO and the SS pin to your MCU.

   

Then you would use the example code provided in the user module datasheet.

0 Likes
Anonymous
Not applicable

As i said in the problem description, the waveform to be decoded is generated from an external non-psoc device. The role of the psoc in my project is to decode the incoming waveform at P1_3 and that is what i am trying to achieve with the interrupts.

   

Thanks

0 Likes
Anonymous
Not applicable

 Could you tell us what is the non-psoc device your are talking about?

   

Do you have access to the other signal of this chip?

   

Can you post a schematic of your current setup?

   

With this information we could help you better design your system.

   

Regards

Anonymous
Not applicable

Unfortunately I haven't yet drawn out the schematic of my circuit. The generated waveform is from a combination of mbed chips and infrared transceivers. I do have access to this part of the system so that i know how the waveform is generated but i am not allowed to change the generated waveform only decode it.

   

Actually my problem isn't about "how do i decode the waveform at P1_3" Its about "how do i get the 2 interrupts to work together" as described in the intial post

   

i.e: - generate gpio interrupt on each falling edge of P1_3, - at 1st falling edge start timer, -at subsequent falling edges update 'newdip', - on every terminal count of timer, check if newdip has been updated, if not update 'value[]', - output 'value[]' at the end

   

Cheers

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Your timer ISR rate is 2.4 Mhz ? That seems to be very aggressive, especially

   

in light of the fact you are calling other functions in it, translate stack pushes, etc..

   

 

   

Regards, Dana.

Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

The timer is fed with 1MHz and has a period of 10 which leads to a rate of 100k interrupts per second. That is pretty fast for a PSoC1. Additionally is your timer-isr is NOT declared with a #pragma instead you save and restore ALL registers with macros in the interrupt handler. That could be optimzed for speed.

   

Your definition for true and false with enum lacks a bit (no pun) of binary. Better (more logical) would be

   

#define FALSE 0

   

#define TRUE !FALSE

   

 

   

which would allow for equivalent constructs like

   

if(b==TRUE)

   

if(b)

   

which would go wrong with your definitions when b is 0xff

   

 

   

Bob

Anonymous
Not applicable

How about this:

   

 

   

Start a 100khz timer when there is a GPIO interrupt, and disable this GPIO interrupt immediately

   

Use the 100khz output as the SPI CK to the SPI.( May need extra hardware for different Mode)

   

Use the SPI interrupt when your SPI is done, and re-enable the GPIO interrupt.
 

Anonymous
Not applicable

Hi there Dana,

   

My timer_isr is fed with 1Mhz and has a period of 10 so that the terminal count occurs every 10us. This is because the frequency of the incoming waveform is 100KHz

0 Likes
Anonymous
Not applicable

Hi there Bob,

   

The reason why the timer is setup this way is because the frequency of the incoming waveform is 100KHz.

   

As you suggested, i have declared the timer_isr with #pragma and changed the lcall directive to ljmp.

   

If you look closely at the code you can see that the variables newdip and firstdip are flags which are only ever assigned 2 values in code i.e. VRAI, FAUX. So there's no way that either of them could have a value of 0xff because i haven't assigned it that way. However I have changed if(firstdip) to if(firstdip==VRAI) and if(!newdip) to if(newdip==FAUX)

0 Likes
Anonymous
Not applicable

Hi there lleung,

   

As i previously explained to EricS, the SPI is not controlled from within the PSoC. So i wouldn't be able to implement your solution

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

@Workplacement (or whatever you'd like to be named)

   

The hint with your self-made booleans is a hint, not more. Only said to prevent you from making mistakes later.

   

Your current code seems to be correct, at least I did not find any direct coding error.

   

But you did not answer about the other issue I mentioned the tight time-span for the interrupt handler  and the different declaration of the interrupt-handlers. When you use #pragma the compiler will save on stack only the used registers (and pseudo-registers, which are a lot!), the macros in the asm-file save all registers always regardless of their use. With #pragma you at least get the chance to optimize your code.

   

Strictly avoid calling ANY function within your handler since then the optimizer looses track of what registers are used and assumes *all*. Is the stopping and re-starting of the timer really needed because that is a function call or can you overcome it with some different coding as accessing the registers directly ?

   

Have a look at the listing to get an impression what all is done just to enter and exit your interrupt- routine: I count something like 64 instructions without your code, just the overhead. 

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 I know you cannot access the source SPI.

   

My idea is use a SPI UM inside your PSOC, the SPI data is connected to p1_3, the SPI CLK is from a timer/counter UM TC/compare output.

   

The p1_3 will generate an GPIO interrupt, inside the interupt, you start the counter/timer and disable this GPIO.

   

use the ouput of the counter/timer to perform as SPI CLK to the SPI in your PSOC. The SPI UM should generate a SPI interrupt after 8(or 9) CLK pulses

   

In the SPI interupt, you can read the SPI data and re-enable the GPIO interrupt and stop you timer/counter UM.

   

This way you only need to handle the first GPIO interutp and the SPI interrupt after all data is received.

lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

With your current setup, how can you detect the start of a frame? The first bit would have to be always low and after the eigth bit the line goes back to high level, which leave you 7bits of data.

   

SPI is a synchronous serial interface, which means there is at least a clock and a data line in the system. The master chip will provide the clock you need. In my first post when I suggested to use SPIS and connect the appropriate signal to the MCU, I meant that the unknown non-psoc device is the master or another chip in your system is the master. The SPIS user module is not generating any clock but wait for an external clock.

   

Look at the project did that I modified.

   

To lleung: If the byte to be received is 0xFF how are you going to trigger your interrupt?

Anonymous
Not applicable

 @EricS,

   

As wordplacement mentioned using the 1st data change to signal a start of transmission. I would assume the 1st bit should alwasy be 0.

   

Should have  wordplacement confirm if that is the case. If it is, the my suggestion should work.

   

If the first bit may be a 1, than there is no way to get the signal back just by checking the data line only.

ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

I may be missing the overall problem points, after all I did ignore your VC3 divider value earlier.

   

 

   

If I understand, you have a SPI byte rate of 100 Khz, therefore a bit rate of 800 Khz,

   

and a Nyquist minimum of 1.6 Mhz to detect a bit ?

   

 

   

Then once you receive byte, byte is a command, that you wish to decode ?

   

 

   

Just trying to confirm design criteria.

   

 

   

Regards, Dana.

Anonymous
Not applicable

In response to lleung and EricS,

   

The SPI generated from the external device is 9 bits not 8 bits. The first bit is always low and thereafter the remaining 8 bits are the actual information that needs to be decoded. So I wait for the first falling edge to detect the start of a frame.

   

I have yet to try both of your solutions. I'll let you people know when i've done so

   

Cheers

0 Likes
Anonymous
Not applicable

Hi there dana,

   

The spi frequency is the bit rate, so for 100KHz each bit is transmitted after 10us leading to a total of 90us.

   

There are 9 bits per frame such that the first bit is always low and the 8 subsequent bits represent the command that needs to be decoded

0 Likes
Anonymous
Not applicable

Hi there bob,

   

I chose the user name 'workplacement' because that's how i would like to be called. I'm not sure why you made such a comment as it is completely irrelevant to the forum post.

   

As i mentioned in my previous response to you, i made some changes to my code as per your suggestions and this didn't solve the problem. The only functions called within the interrupt routines are timer_start and timer_stop. It is absolutely necessary for the timer to be restarted at each interrupt but i'm not too sure about timer_stop so i'll take it out as you suggested and i'll see if that solves my problem

   

Cheers

0 Likes
Anonymous
Not applicable

If your first bit is alwasy low and the following 8 bit is the data.

   

Then I would suggest to use RX8 (RX only UART) and set it to 8N1 with baud rate of 100k

   

your first bit would become the start bit and the next 8 bit decoded by the RX8 logic( the bit is sampled in the middle of the 10us bit time). It should work if there is a least 10us between 2 packet - use it as the stop bit.

   

You only need to have the RX interrup to handle...

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

@Workplacement

   

have a look into the generated sources for the timer and see how (with a macro) the _Stop() and _Start() functions are implemented. I suggest you to declare the ISR-handler with #pragma, removing the save and restore of the processor-state, using an LCALL and having zero function calls within.

   

 

   

Names are not irrelevant for a forum and sometimes the user has a meaning or a story connected to it. So, since the names are related to people and not only to a my computer-screen I am interested in their meaning.

   

 

   

Bob

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given
  
   

@lleung Very clever idea, I like the idea of using UART as gen purpose de-serializer.

   

 

   

Regards, Dana.

0 Likes