How is the port address decoded? - io

According to the image below, it says the output ports are from F0-F7H. My question is how are these ports addresses determine? For example, F0(active low) (Y0) is determine from the inputs A0-A7 inputs? If so, how are these input ports mathematically come to F0?

The 74ALS138 is a 1-8 demultiplexer, this means it takes a number between 0 and 7 and activates one of its eight output lines (active low).
The A, B and C input signals are the three bit encoding the input number (23 = 8) while G1, GA and GB are the enable signals.
To enable the chip G1 must be high and GA and GB must be low, any other combination will disable the chip (all output is high).
To have G1 high we must have the bit 4 of the address high, analogously bit 5, 6 and 7 must be high.
Finally, bit 3 must be low.
This gives an address of the form 1111 0xxx, ranging from 0f0h to 0f7h.
The lowest three bits select the output line.
Regarding the tie between A, B and C and the outputs, you can start with a truth table:
A B C Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7
0 0 0 0 1 1 1 1 1 1 1
0 0 1 1 0 1 1 1 1 1 1
0 1 0 1 1 0 1 1 1 1 1
0 1 1 1 1 1 0 1 1 1 1
1 0 0 1 1 1 1 0 1 1 1
1 0 1 1 1 1 1 1 0 1 1
1 1 0 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1 0
Each output Yi must be computed independently; since each of them is zero exactly once, there is no need to optimize it with a Karnaugh map and since there are a lot of ones, working with Maxterms is definitively better.
So for example for Y0 the formula is
Y0 = A + B + C
Due to the rules when dealing with maxterms (It's a product of sum, each factor being negated iif the input variable is 1).
The other relations are
Y1 = A + B + C'
Y2 = A + B' + C
Y3 = A + B' + C'
Y4 = A' + B + C
Y5 = A' + B + C'
Y6 = A' + B' + C
Y7 = A' + B' + C'
This doesn't take into account the enable inputs, internally we can have a single enable signal E by taking E = G1 * GA' * GB' then the truth table for Y0 becomes
E A B C Y0
0 0 0 0 1
0 0 0 1 1
0 0 1 0 1
0 0 1 1 1
0 1 0 0 1
0 1 0 1 1
0 1 1 0 1
0 1 1 1 1
1 0 0 0 0
1 0 0 1 1
1 0 1 0 1
1 0 1 1 1
1 1 0 0 1
1 1 0 1 1
1 1 1 0 1
1 1 1 1 1
This just translates to Y0 = E' + A + B + C.
If you consider that X + Y === (X' * Y')' by De Morgan's laws and call (X * Y)' NAND you see that Y0 = NAND(E, A', B', C') which is exactly the implementation in the 74ALS138 datasheet:
Datasheet courtesy of Matt Clark

The table in the data sheet seems quite clear: Y0 is active if A0, A1, A2, and A3 are low and A4, A5, A6, and A7 are high. Y1 is active under all the same conditions except A0 is high.

Thanks for the comments to help me connect the dots in figuring out how the address is map to the input address

Related

PYEDA truthtable of functions

Hope there is anybody who feels good with PYEDA.
I want to add fictious variables to function
Let me have f=x1, but how can I get truthtable for this function , which will have x2 too
Like truthtable for f(x1)=x1 is:
x1 f
0 0
1 1
But for f(x1,x2)=x1 is:
x1 x2 f
0 0 0
0 1 0
1 0 1
1 1 1
But I will get first table, pyeda will simplify x1&(x2|~x2) to x1 automatically. How can I add this x2?
def calcFunction(function, i):
#here is is point with dimension-size 4
function=function.restrict({x4:i[3]})
function = function.restrict({x3:i[2]})
function = function.restrict({x2:i[1]})
function = function.restrict({x1:i[0]})
if function.satisfy_one() is not None:
return 1
return 0
Here is my algo to fix it, I am calculating func in each point manually, where function can containt 1-4 variables and I am calculating for all point and combinations of x1...x4.
I'm not sure I understand the question as asked, but you might want to try the expression simplify method.
For example:
In [1]: f = (X[1] & X[2]) | (X[3] | X[4] | ~X[3])
In [2]: expr2truthtable(f)
Out[2]:
x[4] x[3] x[2] x[1]
0 0 0 0 : 1
0 0 0 1 : 1
0 0 1 0 : 1
0 0 1 1 : 1
0 1 0 0 : 1
0 1 0 1 : 1
0 1 1 0 : 1
0 1 1 1 : 1
1 0 0 0 : 1
1 0 0 1 : 1
1 0 1 0 : 1
1 0 1 1 : 1
1 1 0 0 : 1
1 1 0 1 : 1
1 1 1 0 : 1
1 1 1 1 : 1
In [3]: f = f.simplify()
In [4]: f
Out[4]: 1
In [5]: expr2truthtable(f)
Out[5]: 1

How to identify a sequence and index number before a particular sequence occurs for the first time

I have a dataframe in pandas, an example of which is provided below:
Person appear_1 appear_2 appear_3 appear_4 appear_5 appear_6
A 1 0 0 1 0 1
B 1 1 0 0 1 0
C 1 0 1 1 0 0
D 1 1 0 1 0 0
As you can see 1 and 0 occurs randomly in different columns. It would be helpful, if anyone can suggest me a code in python such that I am able to count the number of times '1' occurs before the first occurrence of a 1, 0 and 0 in order. For example, for member A, the first double zero event occurs at appear_2 and appear_3, so the duration will be 1. Similarly for the member B, the first double zero event occurs at appear_3 and appear_4 so there are a total of two 1s that occur before this. So, the 1 included in 1,0,0 sequence is also considered during the count of total number of 1. it is because the 1 indicates that a person started the process, and 0,0 indicates his/her absence for two consecutive appearances after initiating the process. The resulting table should have a new column 'duration' something like this:
Person appear_1 appear_2 appear_3 appear_4 appear_5 appear_6 duration
A 1 0 0 1 0 1 1
B 1 1 0 0 1 0 2
C 1 0 1 1 0 0 3
D 1 1 1 1 0 0 4
Thank you in advance.
A little logic here , first we use rolling sum find the value equal to 0 , then we just need to do cumprod, once it hit the 0, the prod will return 0, then we just need to sum all value not 0 for each row get the result
s=df.iloc[:,1:]
s1=s.rolling(2,axis=1,min_periods=1).sum().cumprod(axis=1)
s.mask(s1==0).sum(1)
Out[37]:
0 1.0
1 2.0
2 3.0
3 4.0
dtype: float64
My logic is checking the current position to next position. If they are both 0, the mask turns to True at that location. After that doing cumsum on axis=1. Locations are in front the first True will turn to 0 by cumsum. Finally, comparing mask to 0 to keep only positions appear before the double 0 and sum. To use this logic, I need to handle the case where double 0 are the first elements in row as in 'D', 0, 0, 1, 1, 0, 0. Your sample doesn't have this case. However, I expect the real data would have it.
cols = ['appear_1', 'appear_2', 'appear_3', 'appear_4', 'appear_5', 'appear_6']
df1 = df[cols]
m = df1[df1.eq(1)].ffill(1).notna()
df2 = df1[m].bfill(1).eq(0)
m2 = df2 & df2.shift(-1, axis=1, fill_value=True)
df['duration'] = df1[m2.cumsum(1) == 0].sum(1)
Out[100]:
Person appear_1 appear_2 appear_3 appear_4 appear_5 appear_6 duration
0 A 1 0 0 1 0 1 1.0
1 B 1 1 0 0 1 0 2.0
2 C 1 0 1 1 0 0 3.0
3 D 1 1 1 1 0 0 4.0
Change your sample to have the special case where the first elements are 0
Update: add case E where all appear_x are 1.
Sample (df_n):
Person appear_1 appear_2 appear_3 appear_4 appear_5 appear_6
0 A 1 0 0 1 0 1
1 B 1 1 0 0 1 0
2 C 1 0 1 1 0 0
3 D 0 0 1 1 0 0
4 E 1 1 1 1 1 1
cols = ['appear_1', 'appear_2', 'appear_3', 'appear_4', 'appear_5', 'appear_6']
df1 = df_n[cols]
m = df1[df1.eq(1)].ffill(1).notna()
df2 = df1[m].bfill(1).eq(0)
m2 = df2 & df2.shift(-1, axis=1, fill_value=True)
df_n['duration'] = df1[m2.cumsum(1) == 0].sum(1)
Out[503]:
Person appear_1 appear_2 appear_3 appear_4 appear_5 appear_6 duration
0 A 1 0 0 1 0 1 1.0
1 B 1 1 0 0 1 0 2.0
2 C 1 0 1 1 0 0 3.0
3 D 0 0 1 1 0 0 2.0
4 E 1 1 1 1 1 1 6.0

How to iterate through 'nested' dataframes without 'for' loops in pandas (python)?

I'm trying to check the cartesian distance between each set of points in one dataframe to sets of scattered points in another dataframe, to see if the input gets above a threshold 'distance' of my checking points.
I have this working with nested for loops, but is painfully slow (~7 mins for 40k input rows, each checked vs ~180 other rows, + some overhead operations).
Here is what I'm attempting in vectorialized format - 'for every pair of points (a,b) from df1, if the distance to ANY point (d,e) from df2 is > threshold, print "yes" into df1.c, next to input points.
..but I'm getting unexpected behavior from this. With given data, all but one distances are > 1, but only df1.1c is getting 'yes'.
Thanks for any ideas - the problem is probably in the 'df1.loc...' line:
import numpy as np
from pandas import DataFrame
inp1 = [{'a':1, 'b':2, 'c':0}, {'a':1,'b':3,'c':0}, {'a':0,'b':3,'c':0}]
df1 = DataFrame(inp1)
inp2 = [{'d':2, 'e':0}, {'d':0,'e':3}, {'d':0,'e':4}]
df2 = DataFrame(inp2)
threshold = 1
df1.loc[np.sqrt((df1.a - df2.d) ** 2 + (df1.b - df2.e) ** 2) > threshold, 'c'] = "yes"
print(df1)
print(df2)
a b c
0 1 2 yes
1 1 3 0
2 0 3 0
d e
0 2 0
1 0 3
2 0 4
Here is an idea to help you to start...
Source DFs:
In [170]: df1
Out[170]:
c x y
0 0 1 2
1 0 1 3
2 0 0 3
In [171]: df2
Out[171]:
x y
0 2 0
1 0 3
2 0 4
Helper DF with cartesian product:
In [172]: x = df1[['x','y']] \
.reset_index() \
.assign(k=0).merge(df2.assign(k=0).reset_index(),
on='k', suffixes=['1','2']) \
.drop('k',1)
In [173]: x
Out[173]:
index1 x1 y1 index2 x2 y2
0 0 1 2 0 2 0
1 0 1 2 1 0 3
2 0 1 2 2 0 4
3 1 1 3 0 2 0
4 1 1 3 1 0 3
5 1 1 3 2 0 4
6 2 0 3 0 2 0
7 2 0 3 1 0 3
8 2 0 3 2 0 4
now we can calculate the distance:
In [169]: x.eval("D=sqrt((x1 - x2)**2 + (y1 - y2)**2)", inplace=False)
Out[169]:
index1 x1 y1 index2 x2 y2 D
0 0 1 2 0 2 0 2.236068
1 0 1 2 1 0 3 1.414214
2 0 1 2 2 0 4 2.236068
3 1 1 3 0 2 0 3.162278
4 1 1 3 1 0 3 1.000000
5 1 1 3 2 0 4 1.414214
6 2 0 3 0 2 0 3.605551
7 2 0 3 1 0 3 0.000000
8 2 0 3 2 0 4 1.000000
or filter:
In [175]: x.query("sqrt((x1 - x2)**2 + (y1 - y2)**2) > #threshold")
Out[175]:
index1 x1 y1 index2 x2 y2
0 0 1 2 0 2 0
1 0 1 2 1 0 3
2 0 1 2 2 0 4
3 1 1 3 0 2 0
5 1 1 3 2 0 4
6 2 0 3 0 2 0
Try using scipy implementation, it is surprisingly fast
scipy.spatial.distance.pdist
https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.pdist.html
or
scipy.spatial.distance_matrix
https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.spatial.distance_matrix.html

How do I create a circuit based on a Boolean function using only a multiplexer?

I need to create a circuit based on the Boolean function: Y = AB’ + B’C’ + A’BC using only an 8 to 1 multiplexer. Then recreate the circuit using only a 4 to 1 multiplexer and NOT gates.
I figured the truth table to be:
A B C | Y
0 0 0 | 1
0 0 1 | 0
0 1 0 | 0
0 1 1 | 1
1 0 0 | 1
1 0 1 | 1
1 1 0 | 0
1 1 1 | 0
But I don't understand how to make the circuit using only a 8 to 1 multiplexer.
Well,
1- Take an 8 to 1 multiplexer
2- Connect A, B y C to the three input
3- connect Y0, Y3, Y4 and Y5 to Vcc, and the rest to ground.
This logical function is made with just one 3x1 multiplexer and no other component.
To make it with 4x1, yo need to connect, for example A and B to the two control inputs, and the 4 input Y0, Y1, Y2, Y3 to the Vcc, ground, C or not(C) as needed, but yo need at least one not gate.
It seem as there is not a solution without a not gate, because por A=B=C=0->Y=1, and A=B=C=1->Y=0

Haskell - counting number of recursions

I have a simple function that calculates the n-th fibonnaci number below:
fibonacci :: Integer -> Integer
fibonacci 0 = 0
fibonacci 1 = 1
fibonacci n = (fibonacci (n-1) ) + (fibonacci (n-2))
But i am interested in a way to count the number of recursions of this function. Any ideas how to do it?
This puts one in mind of sigfpe's illustration of the so-called Writer monad. You might do it a bit more systematically like this:
import Control.Monad.Trans.Writer
import Control.Monad.Trans
import Data.Monoid
fibwriter :: Int -> Writer (Sum Int) Integer
fibwriter 0 = return 0
fibwriter 1 = return 1
fibwriter n = do a <- fibwriter (n-1)
b <- fibwriter (n-2)
tell (Sum (2::Int))
return (a + b)
Used thus:
*Fib> runWriter $ fibwriter 11
(89,Sum {getSum = 286})
This is the same definition, but with the 'side effect' of logging each additional pair of recursions. We can also add a side effect in IO if we want to see all the crazy recalculation involved in the 'naive' definition while it happens:
fibprint :: Int -> WriterT (Sum Int) IO Integer
fibprint 0 = return 0
fibprint 1 = return 1
fibprint n = do a <- fibprint (n-1)
record a
b <- fibprint (n-2)
record b
return (a + b)
where record x = lift (putStr $ ' ' : show x) >> tell (Sum 1)
For fibonacci 11 this gives us this absurdly repetitious show, as the calculation climbs toward 89:
*Fib> runWriterT $ fibprint 11
1 0 1 1 2 1 0 1 3 1 0 1 1 2 5 1 0 1 1 2 1 0 1 3 8 1 0 1 1 2 1 0 1 3 1 0
1 1 2 5 13 1 0 1 1 2 1 0 1 3 1 0 1 1 2 5 1 0 1 1 2 1 0 1 3 8 21 1 0 1 1
2 1 0 1 3 1 0 1 1 2 5 1 0 1 1 2 1 0 1 3 8 1 0 1 1 2 1 0 1 3 1 0 1 1 2 5
13 34 1 0 1 1 2 1 0 1 3 1 0 1 1 2 5 1 0 1 1 2 1 0 1 3 8 1 0 1 1 2 1 0 1
3 1 0 1 1 2 5 13 1 0 1 1 2 1 0 1 3 1 0 1 1 2 5 1 0 1 1 2 1 0 1 3 8 21 55
1 0 1 1 2 1 0 1 3 1 0 1 1 2 5 1 0 1 1 2 1 0 1 3 8 1 0 1 1 2 1 0 1 3 1 0
1 1 2 5 13 1 0 1 1 2 1 0 1 3 1 0 1 1 2 5 1 0 1 1 2 1 0 1 3 8 21 1 0 1 1
2 1 0 1 3 1 0 1 1 2 5 1 0 1 1 2 1 0 1 3 8 1 0 1 1 2 1 0 1 3 1 0 1 1 2 5
13 34(89,Sum {getSum = 286})
recursions :: Integer -> Integer
recursions 0 = 0
recursions 1 = 0
recursions n = recursions (n-1) + recursions (n-2) + 2
For the base cases, there are no recursions, for everything else, we have two direct recursive calls and those that are invoked from the two.
You can also re-use the fibonacci code,
recursions n = 2*fibonacci (n+1) - 2

Resources