Interrupts [again]

edmunds

Senior Member
Dear all,

I'm fighting interrupts here. Again. I have asked questions on this forum and I have presumably working code, but the application differs slightly, but obviously enough not to work. I don't understand how can it be, that I get "Hello from Mars" in my terminal window also when I activate ONLY INT1 with the code below. To add to the confusion, it happens starting with the second time INT1 is activated - the first time works fine. I know the interrupt routine is longish, I will clean it up later.

Code:
Symbol Counter = b5
Symbol row = b6
Symbol col = b7
Symbol CursorPos = b8

init:
  Counter = 0
  CursorPos = 2

  gosub InitDisplay
  gosub ClearDisplay
  gosub StartScreen

  hintsetup %01110111
  setintflags %00001000, %00001000
  
main:
  
  for Counter = 0 to 100
    pause 10
  next Counter
 
goto main

======= some more subroutines here =========

interrupt:
  if UpBtnPin = 1 then interrupt             'loop until interrupt clears - up button is released
  if DnBtnPin = 1 then interrupt             'loop until interrupt clears - down button is released
  if SelBtnPin = 1 then interrupt             'loop until interrupt clears - select button is released
  hintflag = 0
  if hint0flag = 1 then                           'up button pressed
  sertxd ("Hello from Mars", LF, CR)
    Select case CursorPos
    case 2                                                'in case cursor is in upper position of the page, do nothing
    case 3 to 7                                         'otherwise
      gosub ClearCursor                           'clear the current cursor
  		dec CursorPos                                   'decrease cursor position pointer value
  		gosub SetCursor                               'draw the new cursor
  	endselect
  	hint0flag = 0                                     'reset interrupt flags
  endif

  if hint1flag = 1 then                           'down button pressed
    Select case CursorPos
    case 2 to 6                                         'in case cursor not in the bottom position of the page ...
      gosub ClearCursor                           'clear the current position
  		inc CursorPos                                  'increase cursor pointer value
  		gosub SetCursor                              'draw the new cursor
    case 7                                                'in case cursor is in the bottom position of the page, do nothing
    endselect
  	hint1flag = 0                                     'reset interrupt flags
  endif
  
  setintflags %00001000,%00001000
return
Thank you for your time,

Edmunds
 

techElder

Well-known member
The interrupt is disabled when it occurs. You have to reenable the interrupt if you want to see "UpBtnPin" etc. change.
 

westaust55

Moderator
in line with Tex's advise,
A slightly torturous path to follow through the docuemntaiton to glean all the necessary details:
A. From the on-line commands:
http://www.picaxe.com/BASIC-Commands/Advanced-PICAXE-Configuration/hintsetup/
Therefore to have the PICAXE program call the "interrupt:" section of code upon a hardware pin interrupt you must follow two steps:
1) use hintsetup to allow hardware flag setting.
2) then use setintflags to actually generate an interrupt upon the setting of those flags. This means it is possible to interrupt on a combination of any, or all, of the flags via use of the setintflags command. See the setintflags command description for more details. - See more at: http://www.picaxe.com/BASIC-Commands/Advanced-PICAXE-Configuration/hintsetup/#sthash.KM36ItYs.dpuf

B. And then under the Setintflangs online page:
http://www.picaxe.com/BASIC-Commands/Interrupts-and-Multi-Tasking/setintflags/
Please also see the detailed usage notes under the 'setint' command, which also apply to the 'setintflags' command. Only one interrupt can be active at any time. - See more at: http://www.picaxe.com/BASIC-Commands/Interrupts-and-Multi-Tasking/setintflags/#sthash.NurEF9mo.dpuf
C. And finally under the SetInt command:
http://www.picaxe.com/BASIC-Commands/Interrupts-and-Multi-Tasking/setint/
Notes
1) Every program which uses the SETINT command must have a corresponding interrupt: sub-procedure (terminated with a return command) at the bottom of the program.
2) When the interrupt occurs, the interrupt is then disabled and does not automatically re-enable. Therefore to re-enable the interrupt (if desired) when the interrupt processing is finished another SETINT command must be used within the interrupt sub-procedure itself. This interrupt will not be enabled until the interrupt sub-procedure's 'return' command is executed. -
 

hippy

Technical Support
Staff member
You will probably have to put some SERTXD commands in the interrupt routine to show what the state of the interrupt variables are when it is activated and exited. That should show how things are at the time things don't behave as you expect them to and allow the cause to be back-tracked from there.
 

inglewoodpete

Senior Member
Looping within the interrupt routine, waiting for the release of the interrupt source, is very wasteful of processor time.

Since you're already using hardware interrupts (Ie edge triggered), why not configure the interrupts to occur on the release of the button. That way, processing can continue in the main loop until a button press is released.
 

edmunds

Senior Member
Looping within the interrupt routine, waiting for the release of the interrupt source, is very wasteful of processor time.

Since you're already using hardware interrupts (Ie edge triggered), why not configure the interrupts to occur on the release of the button. That way, processing can continue in the main loop until a button press is released.
Thank you, noted, will try that out.

Edmunds
 

edmunds

Senior Member
The interrupt is disabled when it occurs. You have to reenable the interrupt if you want to see "UpBtnPin" etc. change.

I believe from all my heart, that I am doing just that - reenabling the interrupt in the end of my interrupt routine with the SetIntFlags command. I used to have hIntSetup there repeated as well, but since adding or removing it did not seem to change a thing I removed it. The reference was not very definite about weather you would have to reenable the flag setting thing as well, or only the interrupts themselves. My experience would flags need to be "started" only once.

Edmunds
 

edmunds

Senior Member
You will probably have to put some SERTXD commands in the interrupt routine to show what the state of the interrupt variables are when it is activated and exited. That should show how things are at the time things don't behave as you expect them to and allow the cause to be back-tracked from there.

You are right, somehow was tired again or something :). Anyway, for now I designed around this, and it might be better in the end. My main loop now contains only three if statements for the buttons and some delays to debounce. Works way too fast @64MHz unless I add a pause of 1000 inside each if statement :)

Edmunds
 

techElder

Well-known member
You didn't include the code that develops the values for "UpBtnPin" etc. but if your interrupts are disabled, and you loop with "interrupt: if UpBtnPin = 1 then interrupt", tell me how will "UpBtnPin" ever change?


I believe from all my heart, that I am doing just that - reenabling the interrupt in the end of my interrupt routine with the SetIntFlags command. I used to have hIntSetup there repeated as well, but since adding or removing it did not seem to change a thing I removed it. The reference was not very definite about weather you would have to reenable the flag setting thing as well, or only the interrupts themselves. My experience would flags need to be "started" only once. Edmunds
 

edmunds

Senior Member
You didn't include the code that develops the values for "UpBtnPin" etc. but if your interrupts are disabled, and you loop with "interrupt: if UpBtnPin = 1 then interrupt", tell me how will "UpBtnPin" ever change?


Thanks for your input.

Hmm. When UpBtnPin stops being 1, the program moves to the next line(-s), does what has to be done inside the interrupt, resets the interrupt on the way out and returns to whatever it was doing before. If I keep the button pressed, i.e. UpBtnPin is 1, then it does not go anywhere, but that is the point - debouncing. I agree it is not very elegant, but it was suggested by somebody on this forum. Detecting the falling edge is much better, but I had no idea of the concept to even understand what it means back then :). Or am I missing something?

Edmunds
 

inglewoodpete

Senior Member
You didn't include the code that develops the values for "UpBtnPin" etc. but if your interrupts are disabled, and you loop with "interrupt: if UpBtnPin = 1 then interrupt", tell me how will "UpBtnPin" ever change?
I think UpBtnPin is an external input from a pin: "Pin connected to the 'Up' button". That is the only way to get an otherwise unreferenced value to change once execution has entered the interrupt routine.
 
Top