PDA

View Full Version : Truth Tables in PBP



ecoli-557
- 29th August 2014, 20:53
Hey Everyone-
I have queried this forum and have not found much in this area.
I am attempting to 'clone' a logic board which cannot be purchased any longer and is no longer supported for a client. I have all the inputs and results for outputs but my main question is has anyone used a micro in place of logic gates?
I have tried a couple of ways to provide inputs using IF/THEN type statements but it seems clunky and verbose.
Almost think there may be a way to map inputs to EEPROM locations and read data straight out........
Its pretty small; only 4 inputs and 3 outputs and a timing function of 2 seconds.
Curious if anyone has tried to do this?
Thanks in advance for any insight!

richard
- 30th August 2014, 00:01
four inputs
could be
a var portb.0
b var portb.2
c var porta.3
d var portc.3

outputs could be
e var portc.0
f var portc.1
g var portc.2

formula e = a or b and c ,f= d and c or b, g = b and c and d

code
e = (a or b)and c
f= (d and c) or b
g=(b and c)and d

Archangel
- 30th August 2014, 06:43
Select case cleans up on multiple if/then applications, on goto and on gosub work too.

pedja089
- 30th August 2014, 09:38
If you need fast response you can create tables using arrays.
For 4 bit system you have 16 different states, so you create array which hold data for output for every 16 states. And use 4 bits of ports for inputs, and outpust, eg portb0 to Portb3 is inputs, portA0 to 3 are outputs.
TruthTable var byte[16] BANKA'So pbp doesn't need to put banksel after each command
TruthTable[0]=%00001111
TruthTable[1]=%00001100
etc...
TruthTable[15]=%00001111
TRIS...
ANSEL
ETC..
Tmp Var byte BANKA
Main:
Tmp=portb & %00001111
porta=TruthTable[Tmp]
goto Main
This will give almost fastest response for given clock speed.
If you grounded upper nibble, this give you fastest possible responese
Main:
porta=TruthTable[portb]
goto Main
If speed isn't critical you can assign bits to Tmp variable from any pin...

ecoli-557
- 30th August 2014, 21:42
Thanks Guys!
While all are better than what I was playing with, I like the array scheme. I just don't do enough arrays to keep them front and center in my head.
Unfortunately, I didn't have the presence of mind to neatly stack the inputs into a nibble on a port..... using A0, A1, A4, and A5 on a 16F616
I do understand the philosophy, but there is one wrinkle; there are 2 cases in which I need to a pin high, time out for 2 sec and then go low. If the condition on the inputs pins stays the same, the timed pin just stays high.
I even used DT's instant interrupts (so cool) to time the pin but that didn't seem to work.
This should be so easy, but I am missing something and its probably so visible that I can't see it!
What I get when I test my primitive code is the LEDs flash (I use them for debugging) and the timed pin never times out UNTIL the input condition changes. Snippit below:


if command=1 and dpi=0 and bolt=1 and deadlck=1 then
t1=0 : t2=0 : t3=1 'leds
if tflag=1 then Main1X 'been here before so step around
unlock=0
unsecure=0
lock=1 'Turn ON sol
t1=0 : t2=1 : t3=0
pause 2000 'wait 2 sec
t1=0 : t2=1 : t1=1
lock=0 'Turn OFF sol
tflag=1 'We did it so set flag
t1=1 : t2=0 : t3=0
Main1X: t1=1 : t2=0 : t3=1
unlock=0
unsecure=0
endif

EarlyBird2
- 30th August 2014, 22:39
t2 is the timed pin?

is tflag being reset to 0 elsewhere in your code?

Like you I see no problem with this snippet.

Archangel
- 30th August 2014, 23:15
Could be RMW issue if those T# are on same port, better in that case to change them all at once like PortB=%00000100 PortB = %00000011

EarlyBird2
- 31st August 2014, 08:49
Thanks Guys!
While all are better than what I was playing with, I like the array scheme. I just don't do enough arrays to keep them front and center in my head.
Unfortunately, I didn't have the presence of mind to neatly stack the inputs into a nibble on a port..... using A0, A1, A4, and A5 on a 16F616


There are ways around this.

One is to use maths

myvar=PORTA.0+PORTA.1*2+PORTA.4*4+PORTA.5*8

Another way is bit manipulation

myvar=PORTA & %00110011 ' select the input pins
myvar=(myvar & %00000011) + (myvar & %00110000)>>2 'selects A0,A1 then selects A4 and A5 moves then to A2 and A3 and adds to A0,A1

Another way is to set Aliases for the pins which relate to myvar. I will let you look into that one and I am sure there must be other workarounds.

Then myvar can be used in LOOKUP to set an output pattern or used in SELECT CASE or IF THEN, the choice is yours.

ecoli-557
- 1st September 2014, 16:35
Thanks Guys!
I thought there had to be another way....
BTW, it WAS a bug in my code that kept me from the timing sequence. I just tripped out all the code but the one conditional area - code worked like I thought it should.
Then with the entire code back, I systematically remarked all the other places in the code where I zeroed the TFLAG bit var which was in all the other conditionals until it passed the var the way it should.
Turns out you actually can not type using all thumbs! I had mistyped and it was staring me in the face.......

Now that it actually works, its now going to be a learning experience and a life lesson to try these other ways so I may help someone down the road.
Starting with arrays and trying the bit manipulation schemes.......

Thanks and Regards.
Steve

EarlyBird2
- 1st September 2014, 21:28
Now that it actually works, its now going to be a learning experience and a life lesson to try these other ways so I may help someone down the road.
Starting with arrays and trying the bit manipulation schemes.......


You are welcome and if you need more help, as always, just ask.

ecoli-557
- 2nd September 2014, 13:46
Thanks Steve.
I have the array working now, thanks to Pedja089 (Thanks!) and thanks to Steve (EarlyBird2) I have the bit manipulation going.
I have a solution using bit manipulation and Select Case statements which work completely and is more readable than my early attempts at multiple if the statements.
The array idea works well except I can't seem to figure out the timing; on 2 inputs (9 and 11) I have a timing function where an output stays high for 2 seconds then goes low.
For the array, I use


Table var byte[16] BANKA 'Array input is the value of the 4 inputs; 0-15 from the binary weight
tflag var table.3 'timer flag
TableIn var byte 'Entry into array from inputs
temp var byte 'Temp var to use as a debounce


and to get the table data is use


Table[0]=6
Table[1]=2
Table[2]=6
Table[3]=2
Table[4]=6
Table[5]=6
Table[6]=6
Table[7]=6
Table[8]=5
' Table[9]=0
Table[10]=5
' Table[11]=0
Table[12]=4
Table[13]=6
Table[14]=6
Table[15]=6

And for the main part I tried to use


'################################################# ################################################## ######################
'# Subroutines
'################################################# ################################################## ######################

Wait2sec: pause 2000
return

get_input:
TableIn=PORTA & %00110011 'Selects the correct input pins
TableIn=(TableIn & %00000011) + (TableIn & %00110000)>>2
'Selects A0,A1 then selects A4,A5 moves to A2, A3 and adds to A0,A1
'Therefore, the array entry is (Command - DPI - Bolt - Deadlck)
return
'################################################# ################################################## ######################
'# Startmain - where the MAGIC starts!
'################################################# ################################################## ######################
Startmain: 'Main wait loop
gosub get_input 'Get inputs
temp=TableIn
pause 100
gosub get_input
if TableIn <> temp then goto startmain 'Var and temp var did not match so must have been noise, go back
if TableIn = 9 then
if tflag=1 then Main1X
unlock=0
unsecure=0
lock=1
pause 2000
lock=0
tflag=1
Main1X: lock=0
unlock=0
unsecure=0
goto startmain
endif
PORTC=Table[TableIn] 'Sets the port output to the table byte

goto startmain 'Start all over


I use the timing function which seems to work for 1 condition but when I type
if TableIn = 9 or 11 then
as a substitute for just 1 function, it bombs.
The time flag beinig reset for all of the other conditions works for 1 condition but not for an OR condition?
What am I missing now?
-Steve

pedja089
- 2nd September 2014, 15:36
If I was doing same thing I'll set outputs as needed on start of event 9 or 11...
To detect start of event "9" and "11" you can use this code:

IF TableIn=9 AND TableInLast<>9 THEN
'Here you can do what ever needed
ELSEIF TableIn=11 AND TableInLast<>11 THEN
'Sttuf for event 11
ENDIF
TableInLast=TableIn
This way if you have continuous 9 or 11 on input, PIC won't be bricked doing pause...
PAUSE 2000 will block pic to respond to other input states for 2 seconds. I don't know if that can cause problem... But there is way to make timings without using pauses.
First set outputs, and then start timer. And on timer interrupt you turn off timer, and set outputs to default state...
That is pretty easy using DTINT.

HenrikOlsson
- 2nd September 2014, 16:38
Hi,

but when I type if TableIn = 9 or 11 then as a substitute for just 1 function, it bombs.
That won't work because what does If 11 then evaluate to? For that to work it needs to be

IF (TableIn = 9) OR (TableIn = 11) THEN

/Henrik

ecoli-557
- 2nd September 2014, 23:11
Hey There-
I do have it working - came up late last night and my solution looks pretty much like Enrik's suggestion. Code follows for others to use or learn:


'------------------------------------------------------------------------------------------
'Variable List
i var byte 'Loop counter var
Table var byte[16] BANKA 'Array input is the value of the 4 inputs; 0-15 from the binary weight
tflag var table.3 'timer flag
TableIn var byte 'Entry into array from inputs
temp var byte 'Temp var to use as a debounce
'---------------------------------------------------------------------------------------------
'################################################# ################################################## ######################
'# We are going to setup this Pig!
'################################################# ################################################## ######################
Initialize:
unsecure=0 'Esures the relay is not active
lock=0 'Ensures lock valve is not active
unlock=0 'Ensures unlock valve is not active
i=0
Table[0]=6
Table[1]=2
Table[2]=6
Table[3]=2
Table[4]=6
Table[5]=6
Table[6]=6
Table[7]=6
Table[8]=5
' Table[9]=0
Table[10]=5
' Table[11]=0
Table[12]=4
Table[13]=6
Table[14]=6
Table[15]=6

goto Startmain 'Steps around the subroutines
'################################################# ################################################## ######################
'# Subroutines
'################################################# ################################################## ######################

Wait2sec: pause 2000
return

get_input:
TableIn=PORTA & %00110011 'Selects the correct input pins
TableIn=(TableIn & %00000011) + (TableIn & %00110000)>>2
'Selects A0,A1 then selects A4,A5 moves to A2, A3 and adds to A0,A1
'Therefore, the array entry is (Command - DPI - Bolt - Deadlck)
'Remembering that Command and DPI are ACTIVE LOW
'When we get a command to open it is LOW, when door is closed=LOW
'Bolt and Deadlck posotion sensors are ACTIVE HIGH
return
'################################################# ################################################## ######################
'# Startmain - where the MAGIC starts!
'################################################# ################################################## ######################
Startmain: 'Main wait loop
gosub get_input 'Get inputs
temp=TableIn
pause 100
gosub get_input
if TableIn <> temp then goto startmain 'Var and temp var did not match so must have been noise, go back
if TableIn = 9 then
if tflag=1 then Main1X
unlock=0
unsecure=0
lock=1
pause 2000
lock=0
tflag=1
Main1X: lock=0
unlock=0
unsecure=0
goto startmain
endif
PORTC=Table[TableIn] 'Sets the port output to the table byte

goto startmain 'Start all over




I really like the bit manipulation and the use of the tables - a lot.
That's the good news, the not so good news is I have discovered 2 conditions which I hadn't counted;
1. Coming out of the timed function, IF DPI goes from 0 to a 1, I just need to change state of the relay.
IF after staying at 1, DPI goes back to a 0, then start the timing sequence again....... Dang.
2. If after the timed section, if DPI=0 AND deadlock goes from a 1 to a 0 just change the relay state.

Now that I have the truth table, understand the bit manipulation, got the array to work - now I find a 'transitional' state.
Mickey Mouse logic in its day was pretty involved - almost as interesting as the relay-logic trees!

Summation, thanks for the assist, I learned quite a number of 'finer' parts of PBP and registers.
Now I am setting sites on how to know where I am, and watch for certain transitions......

-Steve

ecoli-557
- 3rd September 2014, 03:20
OK, Ive been thinking (with the aid of a glass of Rye.....) and I was wondering with my re-newed knowledge of arrays if the following would work:
1. Have built the truth table - works.
2. Found that there are 'conditionals' within the truth table.
3. What if (new thought here) that a bit or flag is set in the timing section which turns on or activates another section of table!?
4. In my example (I will flesh out the table in the AM) that input 9 or 11 are the timed events. If I set a flag which I can add to the base address of 4 bits (a 5th) and use the newly addressed table for the 2 conditionals!!??
OK, I don't know yet how to do this but tomorrow I will try several trys at this......
Thoughts?

EarlyBird2
- 3rd September 2014, 06:49
OK, Ive been thinking (with the aid of a glass of Rye.....) and I was wondering with my re-newed knowledge of arrays if the following would work:
1. Have built the truth table - works.
2. Found that there are 'conditionals' within the truth table.
3. What if (new thought here) that a bit or flag is set in the timing section which turns on or activates another section of table!?
4. In my example (I will flesh out the table in the AM) that input 9 or 11 are the timed events. If I set a flag which I can add to the base address of 4 bits (a 5th) and use the newly addressed table for the 2 conditionals!!??
OK, I don't know yet how to do this but tomorrow I will try several trys at this......
Thoughts?

Good thinking! Maybe I should try Rye.

Obviously you could use all of the upper nibble as flags giving four sets of special cases if you set them as individual bits. By using the upper nibble as a value then fifteen special cases would be available.

One complication, there is always at least one,

TableIn=PORTA & %00110011

TableIn is reset every time and the bits are manipulated. Obviously there is a workaround. More thinking is required, or Rye?

ecoli-557
- 3rd September 2014, 15:17
Ha! Clearly more of BOTH would be encouraged.......
I'm re-making the truth table with the conditionals. I've always been better at diagramming and such - I'm sure a pattern may arise.
Once I have the new 'map' I'll see what I can do.
As far as TableIn=PORTA & %00110011, The dirty little secret DT showed me may come in handy for the INPUTS as well as it has for the OUTPUTS.
The 'trick' is that the IO is sequential in the memory map, so, just set the base address:
SYMBOL IN_PORT_PIN=PORTA ' starting address
for x=0 to 4 'only 5 inputs for this chip
IN_PORT_PIN.0=[x]
next x

OR just use alias - but that does 'bloat' the code......

ecoli-557
- 8th September 2014, 14:47
OK-
I've worked on this for a bit (no pun) and now I am finding out what the 'conditionals' are are actually edge-triggered events.
I have code which works using flags and if-then-endif style, but my real question is does DT's Instant Interrupts work not only on level conditions - but also for edge level??
I have gone to his page and looked it over, but I do not see any reference to edge-level interrupts.
Should I now start a new thread?

HenrikOlsson
- 8th September 2014, 18:32
Hi,
As far as I know all interrupts are edge triggered or "event triggered" if you will.
Edge on input, mismatch on IOC pins, timer overflowing, byte in UART RX buffer, ADC finished etc.

If you set the interrupt up to fire on the rising edge it will fire on the rising edge. If you then service the interrupt and clear the interrupt flag (which DT-INTS handles for you if you tell it to) it will NOT keep firing until there's a new rising edge on the input.

What interrupt are you thinking of using that you thing may be "level triggered"?

/Henrik.