Interrupts with cli() sei() and EIMSK  = 0x00

Hello,
I have implemented some interrupts in void setup() with:

void setup():

EICRA = 0xF0; //11110000 //RISING edge of INT3) and RISING edge INT2
 EICRB = 0x08; //00001000 //FALLING edge of INT5
 SREG = 1; //s-reg I flag
 EIMSK  |= (1<<INT5); // TURN ON interrupt INT5
 EIMSK  |= (1<<INT3); // TURN ON interrupt INT3
  sei()

Somewhere in my loop() I am trying to pose all interrupts so that I get some time to do stuff and so far I did so by using:

void loop():

[code]
cli() 
[code]  // here interrupts do not work
sei()
[code]

I’d like to know if somebody knows if I can instead do:

void loop():

[code]
EIMSK  = 0x00
[code]   // here interrupts do not work
EIMSK  |= (1<<INT5); // TURN ON interrupt INT5
EIMSK  |= (1<<INT3); // TURN ON interrupt INT3
[code]

results do not seem to be the same… but I am not able to show why and how they are different. Any idea?
thanks
fabrizio

fabrizio, can you say more about what you want your application to do. If you are not familiar with using interrupts then there may be easer ways to do what you want by using the built in arduino functions.

mem,
unfortunately my code is pretty long and if I try to explain the whole I am afraid I will get no help. I will try.

This is the essential part of my code:

void setup(){
  Serial.begin(115200);    // start serial port

  // initialize the interrupts for port PWM3, COM18, COM19
  // PWM3  => INT5  => VSYN
  // COM18 => INT3  => HREF
  // COM19 => INT2  => PCLK
  
  EICRA = 0xF0; //11110000 //RISING edge of COM18(INT3) and RISING edge of COM19(INT2) 
  EICRB = 0x08; //00001000 //FALLING edge of PWM3(INT5)
  SREG = 1; //s-reg I flag
 
  Serial.println("begin processing...");
  EIMSK  |= (1<<INT5); // TURN ON interrup of pin PWM3(INT5) (Arduino Mega Board) VSYN
  EIMSK  |= (1<<INT3); // TURN ON interrup of pin COM18(INT3) (Arduino Mega Board) HREF
  //EIMSK  |= (1<<INT2); // TURN ON interrup of pin COM19(INT2) (Arduino Mega Board) PCLK
  sei();
}

// #### LOOP ####
void loop(){ 
  delay(100);
  while(!begin_frame){} // it pauses until a frame starts
  begin_frame = false;
  while(!begin_line){} // it pauses until a line starts
  begin_line = false;
  EIMSK  |= (1<<INT2); // TURN ON interrupt of pin COM19(INT2) - PCLK
  while(pixel_position<=176){}
  cli(); 
  // now we have one full line
  for (int i = 0; i <= 175; i++){
    Serial.print(ccd_line[i], DEC); Serial.print(",");
  }
  Serial.println();
 sei(); 
}


// #### Interrupt pin PWM3 ####
// this is the VSYN interrupt
ISR(INT5_vect){
  cli();
  //Serial.println("begin frame");
  begin_frame = true;
  sei();
}


// #### Interrupt pin COM18 ####
// this is the HREF interrupt
ISR(INT3_vect){
  cli();
  //Serial.println("begin line");
  begin_line=true;
  pixel_position=0;
  sei();
}


// #### Interrupt pin COM19 ####
// this is the PCLK interrupt
ISR(INT2_vect){
  cli();                           
 ccd_line[pixel_position] = ( (PINL & 0x0f) << 4) | ( (PINB & 0x0f) );
  pixel_position++;
  sei();
}

the code is reading one line (176 byte) of data from a video sensor clocked with PCLK
begin line is synch with HREF interrupt and frame is synch with VSYN.

What do you think? what is your opinion of the implementation? I am a little unsure about how to handle all there 3 interrupts so now I am thinking of turning them on and off so that I can loop the whole thing and get the whole image. For memory reasons I am now thinking of while(pixel_position<=176){} in while(pixel_position<=30){} and use just part of the ccd. The real problem right now is how to handle the interrupts
cheers
fab.
PS PCLK is about 60 KHz.

I would think that you will not have time to do anything else within a line while the data is coming in. a 60khz clock give you 16 microseconds to enter and exit the ISR and process your data. Indeed, I wonder there is enough time to process that data at all (perhaps you can say what your application will do after each line of data and each frame)

Anyway, the practical time available for processing is the amount of time you have during line sync and frame sync (the time when no data is coming in at the end of a line or frame). I think the most efficient way to do what you want is to forget about interrupts and poll for these events.

For example, to start off, wait for frame sync and then monitor the ports to get each byte. You would delay however many microseconds you need such that each byte was sampled in 16 microsecond intervals.

When you have a full line of data you can do a little processing but you need to be ready to detect the start of the next line.

When you have all the lines you can do your frame processing. Again, you must complete this in time to start looking for the beginning of the first line of the next frame.

If you can't fit the processing you need to do within the line and frame blanking intervals (the period of time when no data is being sent at the end of a line and end of a frame) by polling, you will not be able to fit it in using interrupts

hum…
I read from the ATMEGA128 data-sheet that an interrupt take 3 clock cycles (63nsX3=~0.2us) to be executed. I have an interrupt every 16ms

in 16 us i have to do ONLY the following:

// #### Interrupt pin COM19 ####
// this is the PCLK interrupt
ISR(INT2_vect){
cli(); 
ccd_line[pixel_position] = ( (PINL & 0x0f) << 4) | ( (PINB & 0x0f) );
pixel_position++;
sei();
}

16us should be enough. what do you think?
after 167 time (end of line), I see form my oscilloscope that i have more about 8ms to pack part of the line, maybe the first 50 pixels (simple case) is an array.
At the end of the frame I see that I have about 45 ms to send via the serial the whole image. What do you think?

I remember your advise not to go through interrupts and I respect that and I think you are right. The truth is that for me this is also a learning experience and a series of reasons I used interrupts. My second implementation will be inline with ur original advise :wink:

How would you suggest to pause the PCLK interrupt during those 8ms? EIMSK = 0x00
and //EIMSK |= (1<<INT2); is a good idea? what is the use of sei()?

thanks a lot for your time
fabrizio

The actual overhead will be much greater than three cycles because the low level runtime code will save and restore the value of the registers on each interrupt call.

If you have no previous experience with using interrupts I suggest you get the application going first without them. Personally, I find its difficult enough to debug high speed interrupt code when its running on the bench in front of me (and I have logic analyzers and scopes to help me see what is going on) , it would be very hard to help you remotely.

Just my 2cents

thanks for your advise ;)

cheers fab.

discussion continues here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1246983406/4#4