RE: Pokesfr and the Program Counter

otm

Member
RE: Pokesfr and the Program Counter

Hello Everyone,

Long time no see!!

I'm in the middle of programming a 14M2 to operate a robotic trailer. In essence, its for a Uni Group project involving an NI DANI robot, and a Lynxmotion Brat and Tri-Track, ohh, and a Barbie (Don't ask)

the NI DANI needs to be able to control a trailer, which will allow the Lynxmotion Tri-Track to get on and off (as autonomously as possible).

I have created code for the 14M2 that connects to an AXE024 for servo control (Tailgate of the trailer) in normal operation, this follows a normal (and simple) sequence of opening the gate, unloading the Tri-Track, waiting, waiting for sensor information to detect the Tri-Track has come back onto the trailer and is waiting, then closing the tailgate and sending a pulse back to the NI DANI which goes off and does its stuff, waiting for another command to repeat the process...

However, I have created an interrupt for the eventualilty that, during the project Scenario, the group decides to unload the Tri-Track, and for whatever reason, leave it off the trailer and use the NI DANI seperatly.

My problem is, the interrupt (as it should) returns where it was before being called, for me, this isn't what I want.

My immediate reaction was 'Surely there must be a way to alter the program counter' to either jump the program to the beginning performing in essence, a reset, or to jump back to a certain section of the code.I thought this will be easy-ish (I understand not the best thing to do, but it should work), However, I have found information about pokesfr to enter the special function register, but no information as to the whereabouts of the PC itself, I have seen snipets using poke to 'reset' but they don't simulate to well, and As I'm not in a position to say that its correct or not, I thought it best to ask.

Any ideas?

Cheers,

Owen.
 

MartinM57

Moderator
You won't be able to find the PC in interpreted PICAXE BASIC - and directly modifying program counters is pretty bad practice anyway (well, actually it's very bad practice)

You will have to get the interrupt to communicate back to the main program by using a variable set in the interrupt and read by the main program.

Why do you have an interrupt to detect this condition anyway? What triggers the interrupt...more detail needed :D
 

srnet

Senior Member
Any ideas?
Yes.

You cannot alter the 'program counter' (whatever that meansto you) to jump arbitary positions in the PICAXE program, and neither could you know where these positions were in the first place.

You might want to decribe what it is you are trying to do, and I hope I am not the only person who has not a clue what this all means or describes;

"its for a Uni Group project involving an NI DANI robot, and a Lynxmotion Brat and Tri-Track, ohh, and a Barbie (Don't ask)"
 

Technical

Technical Support
Staff member
Normal way to handle this kind of thing would be to set a flag (e.g. b1 = 1) within your interrupt and then check for that flag within your main program loop.

The lazier way may be to put a 'reset' command within your interrupt.
 

otm

Member
You won't be able to find the PC in interpreted PICAXE BASIC - and directly modifying program counters is pretty bad practice anyway (well, actually it's very bad practice)

You will have to get the interrupt to communicate back to the main program by using a variable set in the interrupt and read by the main program.

Why do you have an interrupt to detect this condition anyway? What triggers the interrupt...more detail needed :D
Martin,

I appreciate, altering the PC is not good practice, I appreciate it causes issues, and whathave you,

the interrupt is triggered by a pulse from the NI DANI robot, which is controlled via labview.


Yes.

You cannot alter the 'program counter' (whatever that meansto you) to jump arbitary positions in the PICAXE program, and neither could you know where these positions were in the first place.

You might want to decribe what it is you are trying to do, and I hope I am not the only person who has not a clue what this all means or describes;

"its for a Uni Group project involving an NI DANI robot, and a Lynxmotion Brat and Tri-Track, ohh, and a Barbie (Don't ask)"
Surely the Picaxe needs to know where its going? there will be part of the processor that deals with this, along with exceptions and memory management, if it can be accessed and altered seems to be a whole other issue..... I appreciate that all my dealings with status registers and Program counters is using ARM Assembly, but even with all the differences surely there is some similarity?

As for the project, we have to use the listed robots, to get from a home base to another location, steal an opositon Barbie doll, take it back to our base, and then try and retreive our Barbie from the oppositions base. The aim is to be autonomous (within reason).


Normal way to handle this kind of thing would be to set a flag (e.g. b1 = 1) within your interrupt and then check for that flag within your main program loop.

The lazier way may be to put a 'reset' command within your interrupt.
I was trying to avoid using 'Reset' if I can help it, but it seems like the only real way at the moment.

you mention about setting a flag (along with Martin) I trying to work out how to implement that, below is my code (It may not be the greatest, but, with minor changes it will do everything it needs)

Code:
#picaxe 14M2


symbol tail_open = 110
symbol tail_closed = 190
setint %00000001,%00000001  'Set an Interrupt on pinc.0 to look for the pin to go high


inputcheck:

if pinc.1 = 1 then 
	{
	  	gosub open
		gosub unload
		gosub load
		gosub close
	  	gosub notice
	  

	}
endif	  
	 	
goto inputcheck





open:


do until pinb.1 = 1
{
	high b.4 'toggle the line to trigger the interrupt
	pause 2
	low b.4
	pause 2
	serout b.4,N2400, (tail_open) 'Output the data
	pause 2
}
loop
pause 500
return

close:


do until pinb.1 = 0
{
	high b.4 'toggle the line to trigger the interrupt
	pause 2
	low b.4
	pause 2
	serout b.4,N2400, (tail_closed) 'Output the data
	pause 2
}
loop
pause 500
return


load:

do until pinb.2 = 0 AND pinb.3 = 0
{
	pause 1000
}
loop
return

unload:

do until pinb.2 = 1 AND pinb.3 = 1
{
	pause 1000
}
loop
return


notice:

high c.2
pause 1000
low c.2
return

interrupt:

do until pinb.1 = 0
{
	high b.4 'toggle the line to trigger the interrupt
	pause 2
	low b.4
	pause 2
	serout b.4,N2400, (tail_closed) 'Output the data
	pause 2
}
loop
pause 500
return
setint %00000001,%00000001  'Set an Interrupt on pinc.0 to look for the pin to go high
'''''SOMETHING HERE
return
Thanks for all your replies,

Owen.
 
Last edited:

KeithRB

Senior Member
There are *two* "program counters" here. One which the interpreter machine code uses - the underlying PC of the machine. And the other is the BASIC level one that is used by the interpreter to keep its place in your program. Obviously the low level one is not much use to you, and I don't think it is a good idea to play with the other, even if you could access it.
 

otm

Member
Hello,

From my reading of the responses, this is a null and void question,

I suppose it was worth a go!

I will probably place a reset inside the interrupt. It's not a nice piece of code, but at the end of the day, it does the desired job, and the majority problems it causes are irrelevant!

Using the PC during all my ARM work, where changing the PC for custom Exception Vectors and the like is easy, I did lose sight of that fact that that is assembly language!!


Cheers for all your input,

Owen.
 

westaust55

Moderator
The POKESRF and PEEKSRF deliberately do not give access to the lower (from memory) 12 registers in each block where the PIC PC is located.
Part of the reason is the number of registers exceeds the 256 location/register capability of the POKESRF and PEEKSRF commands, and
secondly Rev Ed do not wish folks to be poking into register that are specifically under interpreter control and un coordinated changes may cause craashes or mal-operation.

Why not set up a flag as already mentioned. At the start of the program assign the value 0 to the flag. When the interrupt routine is called set the flag to the value 1.
Now when you return to the main loop, if the flag is set to 1, then the main loop can branch or gosub to the desired location.
How often and where in the Main loop you scan to check the status of the "flag" is dependant upon what other tasks are to complete first.

as a simple example in the absence of clear details:
Code:
[COLOR="#FF0000"][B]SYMBOL flag = bit0
init:
	Flag = 0[/B][/COLOR]



inputcheck:

[COLOR="#008000"]	DO
[/COLOR]		if pinc.1 = 1 then 
		{
	  		gosub open
			gosub unload
			gosub load
			gosub close
	  		gosub notice
	  

		}
		endif	  
[B][COLOR="#FF0000"]		IF Flag = 1 THEN
			do something here
		ENDIF[/COLOR][/B]
[COLOR="#008000"]	LOOP ; loop forever[/COLOR]




open:
	do until pinb.1 = 1
	{
		high b.4 'toggle the line to trigger the interrupt
		pause 2
		low b.4
		pause 2
		serout b.4,N2400, (tail_open) 'Output the data
		pause 2
	}
	loop
	pause 500
	return

close:
do until pinb.1 = 0
{
	high b.4 'toggle the line to trigger the interrupt
	pause 2
	low b.4
	pause 2
	serout b.4,N2400, (tail_closed) 'Output the data
	pause 2
}
loop
pause 500
return


load:

do until pinb.2 = 0 AND pinb.3 = 0
{
	pause 1000
}
loop
return

unload:

do until pinb.2 = 1 AND pinb.3 = 1
{
	pause 1000
}
loop
return


notice:

high c.2
pause 1000
low c.2
return

interrupt:

do until pinb.1 = 0
{
	high b.4 'toggle the line to trigger the interrupt
	pause 2
	low b.4
	pause 2
	serout b.4,N2400, (tail_closed) 'Output the data
	pause 2
}
loop
pause 500
return
[B][COLOR="#FF0000"]Flag = 1[/COLOR][/B]
setint %00000001,%00000001  'Set an Interrupt on pinc.0 to look for the pin to go high
'''''SOMETHING HERE

return
 

inglewoodpete

Senior Member
The safest way to alter the program counter in most programming languages is to use GoTo and a label. :):):)

However, it does not change the subroutine return "stack" but neither does changing the program counter, even if you could.
 

hippy

Technical Support
Staff member
From my reading of the responses, this is a null and void question,
In general yes. If familiar with Windows / GUI programming in a high level language what you are asking for is similar to code within a button click handler being able to change the operation of the code running in an entirely separate thread.

Threads may however be the answer, if you think of the M2's multi-tasking as threads, only partially tested ...


Code:
Start0:
  SerTxd( "Main Thread Restart", CR, LF )
  Do
     SerTxd( "X" )
     Pause 100
  Loop

Start1:
  Gosub Interrupt_Enable
  Do
    If irqFlag = 1 Then
      irqFlag = 0
      Restart 0    
    End If
  Loop

Interrupt:
  irqFlag = 1

Interrupt_Enable:
  SetInt ...
  Return
 

otm

Member
Hi Guys,

Thanks for your responses,

It's been a while since I've done this, Hence the question, and In reality, the following code using the flag method works:

Code:
#picaxe 14M2


symbol tail_open = 110
symbol tail_closed = 190
setint %00000001,%00000001  'Set an Interrupt on pinc.0 to look for the pin to go high
b0 = 0

inputcheck:

if pinc.1 = 1 then 
	{
		sertxd ("input check", cr)
	  	gosub open
		gosub unload
		gosub load
		gosub close
	  	gosub notice
	  

	}
endif	  
b0 = 0	 	
goto inputcheck





open:


do until pinb.1 = 1
{
		sertxd ("open", cr)
	high b.4 'toggle the line to trigger the interrupt
	pause 2
	low b.4
	pause 2
	serout b.4,N2400, (tail_open) 'Output the data
	pause 2
}
loop
pause 500
return

close:


do until pinb.1 = 0
{
		sertxd ("close", cr)
	high b.4 'toggle the line to trigger the interrupt
	pause 2
	low b.4
	pause 2
	serout b.4,N2400, (tail_closed) 'Output the data
	pause 2
}
loop
pause 500
return


load:
		
do until pinb.2 = 0 AND pinb.3 = 0 
{
	sertxd ("load", cr)
	pause 1000
	if b0 = 1 then
	{
		return
	}
	Endif
}
loop
return

unload:

do until pinb.2 = 1 AND pinb.3 = 1
{
sertxd ("unload", cr)
	pause 1000
}
loop
return


notice:
sertxd ("notice",cr)

high c.2
pause 1000
low c.2
return

interrupt:
setint %00000001,%00000001  'Set an Interrupt on pinc.0 to look for the pin to go high
b0 = 1
return
I realised, late last night (as all good ideas are) that all I wanted to do was interupt the Load subroutine, to make it terminate early. So, using a Flag bit, this is acheived, I have however, learnt along the way some interesting things, and Hippy, I will read more into threads out of sheer interest.

As to what you are saying with windows/GUI programming, the highest I've got is C++, and I can get your analogy. In C++ for example I can overload operator functions such as << and >> but even though that could be perceived as altering the functions function, its not.


Thanks for Everyones help.

No doubt I will be back with another Thread as and when I need it!!

Owen.
 
Top