## The unaligned bridge

### The unaligned bridge

Isn't it a bit quiet in CLAX recently ?

I just stumbled over some of my old stuff and if there is
anybody interested we can discuss ASM solutions for it.

Almost forty years ago I wrote a BASIC-programm for
calculation of all values on a bridge like this:

___ + ___
o-|___|----o----|___|-o
| R1 | R2 |
| _ |
| | | |
| | |R5 |
| |_| |
| ___ | ___ |
o-|___|----o----|___|-o
| R3 R4 |
| |
+o <-Rt/Ut-> o

(polarity shown for I5,U5 results)

Inputs: R1,R2,R3,R4,R5,Ut
Outputs: I1,I2,I3,I4,I5,It
U1,U2,U3,U4,U5,Rt

And also possible were all other input/output
combinations like the classic:
Given: R1,R2,R3,R5,Ut,I5 or U5
Wanted: R4 (and all other as side-results)

So it needs 6 (indexed) inputs and 12 outputs beside
some temporary values.
When I look at 64/128-bit SSE-functions for packed
single precision they could fit well here.

__
wolfgang

### The unaligned bridge

Well, I dug out my Electrical Circuits 101 textbook so that I can race you
to the solution. ;-)

We will not know the true polarity until we know in which direction it is
unballanced.

m'kay...

Until version 7.9, all of that will be coded as:

stdout.put( "This feature not yet implemented.")

Yes, DIVPS would see a lot of use.

Nathan.

### The unaligned bridge

I take it U is voltage.

6 resistors? I can't imagine what you'd use that for... In those forty
years, have you ever needed this? What for?

Bridges, of any type, as a component, have limited use in electronics.
Other components are used far more frequently. That's not saying they
aren't very useful or aren't used often: bridge recifiers for AC
rectification, H-bridges for motor controllers, Wien bridge, Wheatstone,
etc.

IIRC, the EE circuit designers I once worked with said that there are enough
standard resistor values that they only very rarely needed a pair of
resistors to create a non-standard value. Now, a hobbyist probably doesn't
want to stock all the numerous standard resistor values. So, a program that
minimized the resistors needed to create a specific resistance, while
maximizing the number of possible or standard resistance values might be
useful. It could take part tolerances into account too. For two resistors
in parallel, that should nonuple the math computations.

Rod Pemberton

### The unaligned bridge

Rod Pemberton replied:

Yeah.

Only five and the Total seen by the power source.

This example covers the basic calculation for cross-currents
which you find wherever you look in any electronic circuit.

The complete final formular is "complex" (math. and literally)
and work on Z1..Z5 (vectored impedance) rather than on resistors.

And this current-net (aka matrix) calculations are more vital
today for PCB-layout and chip-design than in the past, because
we are already close to physical limits and parasite impedance
cannot be ignored anymore.

Yes, any practical use for the scematic above cover only a few
applications, like nonlinear amplifiers and a couple of measure-tools.

Ok, but this is not the reason for such a circuit.

If you look at the scematic again and replace R5 with an Ampere-
meter (got a known resistance) and one of the other resistors
ie: R4 with a potentiometer...
What kind of curve would you expect if you plot I5 for R4-range?
and how will this affect the total current drawn ?

one example for practical usage:
how much would a parasite Z5 affect max.speed and the powerdrain
of two close power-consumers (think about RAM-cell drivers).

__
wolfgang

### The unaligned bridge

Nathan Baker replied:
...

:)

Right, but we must define a polarity reference to the source
otherwise we couldn't tell the direction ;)
And btw, I just see that I typed the I5 sign on the wrong end
in accordance to my used formula.

:) ok so far. version 1001 may then cover the complex formular.

Unfortunately DIV are required because I wrote the formular
as a set of current relations to Ut and It, but the main
lines contain only MUL and ADD.

Rt = Ut/It

Ut: r1*r2*r3+r1*r2*r4+r1*r3*r4+r2*r3*r4+r5*(r1+r2)*(r3+r4)
It: r5*(r1+r2+r3+r4)+(r1+r3)*(r2+r4)
I1: r3*(r2+r4)+r5*(r3+r4)
U1: r1*I1
and so on...until
I5: r1*r4 - r2*r3
U5: r5*I5

And if only four resistors are known we need to know
two other parameters for calculation of the fifth Rx.

So we always need six input-values and better mark them with
indicies (1..18) to avoid the huge amount of code variants
for all the possible input combinations.

I can also think about a defined array (value+tag) where inputs
and results live at fixed offsets.
This way we could fill the array with the known, mark the other
as unknown and just tell it to calculate all.
__
wolfgang

### The unaligned bridge

Since it's been quiet.

Andy

;clip.asm Use to "pre-fill" the clipboard for later use
;
include \masm32\include\masm32rt.inc

.data

hglb dd 0 ;
str1 db 'Have a great day.'

.code

start:

;------------------------------
; Place str1 on the clipboard.
;------------------------------

invoke OpenClipboard,NULL
.IF (eax)
invoke EmptyClipboard
invoke GlobalAlloc,GMEM_MOVEABLE,SIZEOF str1
.IF (eax)
mov hglb, eax
invoke GlobalLock,hglb
;---------------------
; Pointer now in eax.
;---------------------
invoke GlobalUnlock,hglb
invoke SetClipboardData,CF_TEXT,hglb
;--------------------------------------------
; System now owns object identified by hglb.
;--------------------------------------------
.IF (eax == 0)
print "SetClipboardData failed",13,10
.ENDIF
.ELSE
print "GlobalAlloc failed",13,10
.ENDIF
invoke CloseClipboard
.ELSE
print "OpenClipboard failed",13,10
.ENDIF

exit
end start

### The unaligned bridge

Correct. My textbook labels those nodes as A and B; that way we could
answer with "current will flow from A to B" in our homework. But your idea
of having a reference on the schematic is best for a program -- the sign of
the result will tell the user the direction.

Yes, and if I rotate your diagram 15 minutes clockwise and swap the R1 & R2
with R3 & R4 labels, then it'd match my book. :)

Mine are different. We start by checking for balance:

See if the ratio R1 / R2 is equal to the ratio R3 / R4?

If not, then the larger ratio represents the drain node [negative
potential].

Continue with finding [via voltage division] the voltage drops across the
resisters:

Vr1 = Ut * R1 / ( R1 + R2 )
Vr2 = Ut * R2 / ( R1 + R2 )
Vr3 = Ut * R3 / ( R3 + R4 )
Vr4 = Ut * R4 / ( R3 + R4 )
Vr5 = Vr2 - Vr4

Then, Voltage law ( E = I * R ) will give us the currents:

I1 = Vr1 / R1
I2 = Vr2 / R2
I3 = Vr3 / R3
I4 = Vr4 / R4
I5 = Vr5 / R5

If the computer does all the "thinking", then what use for the human?? :)

Nathan.

### The unaligned bridge

I hope the CPU understands imaginary numbers. ;)

Like for a temperature sensor connected to an alarm. You've determined that
your source voltage has occasional peeks and dips -- you don't want these to
"set off" your alarm unintentionally. The bridge circuit forces the alarm
to only respond to the temp sensor changes and to ignore the source voltage
changes.

Not just any ammeter, but an extra-sensitive one called a galvanometer.

The Wheatstone bridge. Not to be confused with the San Francisco bridge.
:)

Nathan.

### The unaligned bridge

Andy posted:

| Since it's been quiet.

my 32-bit environment may allow a shorter variant:

.data
msg: "I have plenty of great time because my code is short"
msgcnt: sizeof msg
origin: dd 0
.code
do_it:
mov ecx,msgcnt
cld
mov edi,clip_ptr ;points to clipboard header
cmp [edi],ecx ;first dw is max. clip_size
mov origin,edi ;save clip_ptr
jc done ;set carry if too large
mov esi,msg
add edi,4 ;no carry to expect here
rep movsb
mov [edi],00000a0dh ;CR-LF and zero mark at end
mov clip_ptr,eax ;make this string non-temporary
done: ;ignore and do nothing if too large
ret
_______________________________________________________
;clip.asm Use to "pre-fill" the clipboard for later use
;
include \masm32\include\masm32rt.inc

.data

hglb dd 0 ;
str1 db 'Have a great day.'

.code

start:

;------------------------------
; Place str1 on the clipboard.
;------------------------------

invoke OpenClipboard,NULL
.IF (eax)
invoke EmptyClipboard
invoke GlobalAlloc,GMEM_MOVEABLE,SIZEOF str1
.IF (eax)
mov hglb, eax
invoke GlobalLock,hglb
;---------------------
; Pointer now in eax.
;---------------------
invoke GlobalUnlock,hglb
invoke SetClipboardData,CF_TEXT,hglb
;--------------------------------------------
; System now owns object identified by hglb.
;--------------------------------------------
.IF (eax == 0)
print "SetClipboardData failed",13,10
.ENDIF
.ELSE
print "GlobalAlloc failed",13,10
.ENDIF
invoke CloseClipboard
.ELSE
print "OpenClipboard failed",13,10
.ENDIF

exit
end start
________

### The unaligned bridge

Nathan Baker wrote:

...

Yes it could help to avoid div/0 by treating the 'special case' apart.

Your book is right for practical close results if R5 is high
in relation to the other four resistors.
My formula (written on a form :) include the influence of
current-flow over R5. This current must come from somewhere ... ;)
It either adds to I1 and I4 or I2 and I3, and this affects
all other relations and the totals as well.

let me check the difference on one theoretical example:
Ut = 100 Volt,
R1 = 1, R2 = 2, R3 = 3, R4 = 4 and R5 is 5 Ohm

your result for U5 and It will be:
Vr2 - Vr4
100*2/(1+2) - 100*4/(3+4) = 200/3 - 400/7 = 200/21
U5 = 9.523809 Volt
It = 100/3 + 100/7 = 47.61904 Ampere
________________
my form:

1*2*3 +1*2*4+ 1*3*4 +2*3*4 +5*(1+2)*(3+4) 155 (=Ut-part)
Rt= ----------------------------------------- = --- = 2.09249 Ohm
5(1+2+3+4) +(1+3)*(2+4) 74 (=It-part)

It= 100/Rt = 47.74419 Amps, Not much difference to yours, but...

It: 5*(1+2+3+4) + (1+3)*(2+4) = 74
I5: r1*r4 - r2*r3 = -2

so I5:It = -0.0270

I5 = -0.0270270 * 47.74419 = -1.29038 Ampere
U5 = I5*R5 = -6.451917 Volt, let asside sign, you'd be ~50% off yet!

to confirm my calculation I check on all other resistors:

U1:Ut
I yet remeber the Ut/It-parts from the above = 155/74 and set it
in relation to these:

I1: 3*(2+4)+5*(3+4) = 18+35 = 53 ; It*53/74 = 34.1935 Amp
U1: 1*(3*(2+4)+5*(3+4)) = 53 ; Ut*53/155 = 34.1935 Volt

I2: 4*(1+3)+5*(3+4) = 16+35 = 51 It*51/74 = 32.9048 Amp
U2: 2*I2 = 102 ; Ut*102/155 = 65.8065 Volt

I3: 1*(2+4)+5*(1+2) = 6+15 = 21 It*21/74 = 13.5490 Amp
U3: 3*I3 = 63 ; Ut*63/155 = 40.6450 Volt

I4: 2*(1+3)+5*(1+2) = 8+15 = 23 It*23/74 = 14.8394 Amp
U4: 4*I4 = 92 ; Ut*92/155 = 59.3550 Volt

You see that U1+U2 = U3+U4 = Ut = 100 Volt
and U1-U3 = U4-U2 = U5 =-6.4519 Volt
Also the currents show from where R5 draw its power
that I1+I3 = I2+I4 = It = 47.74419 A
and I3-I4 = I2-I1 = I5 = -1.29038 A.

So in this example I5 creeps over R4 and R1:
___ A ___
o-|___|-<<-o----|___|-o
| R1 | R2 |
| _ |
| | | |
| | |R5 |
| |_| |
| ___ | ___ |
o-|___|----o-<<-|___|-o
| R3 B R4 |
| |
o <-Rt/Ut-> o
B A
_____________________________________
I see no flaw in this yet.
but may expect a few of my regular typos :)

****************************************************************
A brief warning for those who like to see this on real hardware:
either replace Ohms with Mega-Ohms or work with Milli-Volts or
****************************************************************

programmers type-in correct code and users valid values ? :)

__
wolfgang

### The unaligned bridge

> ov edi,clip_ptr points to clipboard header> > mp [edi],ecx ;first dw is max. clip_s>ze
> ov origin,edi save cl>p_ptr
> c done ;set carry >f too large
> >mov esi,msg
> dd edi,4 ;no car>y to expect h>re
> ep movsb
> ov [edi],00000a0dh ;CR-LF and>zero mark at end
> ov clip_ptr,eax make this s>ring non-temporary
> done: ignore >nd do n>thing if too large
> et
> ____________________________>__________________________
> ;clip.asm Use to "pre-fill" >he c>ipboard for later use
> ;
> include>\m>sm32\inclu>e\>asm32rt.inc
> >> .data
>
> hglb dd 0 ;> >>str1 db >Ha>e a great>da>.'
>
> .code
>
> start:
>
> ; Place str1 on the clipboar>. >> ;----------------------->------
>
> gt;invoke OpenClipboard,NULL> > .IF (eax)
> invoke EmptyClipboard
>>invoke Gl>balAlloc,GMEM_MOVEAB>E,SIZEOF str1
> .IF (e>x)
> mov hglb, eax
>>invoke GlobalLock,hgl>
> ;--------------->-----
> ; Pointer now in eax.
> gt;;---------------------
> invoke GlobalUnlock,hglb
> i>voke SetClipboardData,CF_TEXT,hglb
> ;--->----------------------------------------
> gt;; System now owns obj>ct identified by hglb.
> ;-------->------------->----------->---------
> .IF (eax == 0)
> > pri>t "SetClipboardData failed">13,10
> gt;.ENDIF
> .ELSE
> p>int "Global>ll>c failed">13,10
> gt;.ENDIF
> invoke CloseClipboard

Thanks Wolfgang.

Andy

### The unaligned bridge

n Nov 14, 5:26m, Andy < XXXX@XXXXX.COM >
wrote:
> > ov origin,edi save cl>p>ptr
> > c done ;set carry >f>too large
> > >m>v esi,msg
> > dd edi,4 ;no car>y>to expect her> >> > ep movsb
> > ov [edi],00000a0dh ;CR-LF and>z>ro mark at end
> > ov clip_ptr,eax make this s>r>ng non-temporary
> > done: ignore >n> do not>i>g if too large
> > et
> > ____________________________>_>________________________
> > ;clip.asm Use to "pre-fill" >h> cli>b>ard for later use
> > ;
> > include>\m>s>32\include>ma>m>2rt.inc
>
> >>gt;.data
>
> > hglb dd 0 ;
> > .code
>
> > start:
>
> > > ;------------------------------ >>>> ; Place str1 on the clipboard.> >>>>;------------------------->->--
>
> > gt;i>voke OpenClipboard,NULL
> > > .IF (eax)
> > invoke EmptyClipboard
> >>gt;invoke Glob>l>lloc,GMEM_MOVEABLE,S>Z>OF str1
> > .IF (eax) >>>> mov hglb, eax
> > gt;gt;invoke GlobalLock,hglb
>>>>;------------------->-> > > ; Pointer now in eax.
> > gt;gt;;---------------------
> > gt;gt;invoke MemCopy,ADDR str1,eax,SIZEOF str> >> > invoke GlobalUnlock,hglb
> > inv>k> SetClipboardData,CF_TEXT,hglb
> > ;----->->------------------------------------
> > ;>S>stem now owns object >d>ntified by hglb.
> > ;------------>->------------->->----------->-> > > .IF (eax == 0)
> > > > print "SetC>i>boardData failed",13,10
> > > .EN>I>
> > .ELSE
> > print "Gl>b>lAlloc fail>d">1>,10
> > > > .ENDIF
>>>>invok> C>oseClipboard
> > gt;>ELSE
> > print "OpenClipboard failed",13,10
> > .ENDIF
>
> > exit
> > end start
> > ________
>
> Thanks Wolfgang.
>
> Andy

I am converting the code to masm format.

I am having problems.
Difficulty in understanding pointers, ADDR, etc.

Thanks,
Andy

..686
..model flat, stdcall
option casemap :none

include \masm32\include\windows.inc
include \masm32\include\masm32.inc

msgcnt equ sizeof msg

..data

msg db "I have plenty of great time because my code is short.",0
origin dd 0
clip_ptr db 50 dup(0)

..code

start:

do_it:
mov ecx,msgcnt
cld
mov edi,byte ptr clip_ptr ;points to clipboard header
cmp [edi],ecx ;first dw is max. clip_size
mov origin,edi ;save clip_ptr
jc done ;set carry if too large
mov esi,byte ptr msg
add edi,4 ;no carry to expect here
rep movsb
mov [edi],00000a0dh ;CR-LF and zero mark at end
mov clip_ptr,eax ;make this string non-temporary
done: ;ignore and do nothing if too large
ret

end start

### The unaligned bridge

Andy figured it wont work...:

...
Sorry for the confusion.
That's why I mentioned "my" environment which is quite
different to the windoze-API.
So you can't use my code on windoze as it is.
some modification will be required ...

|I am converting the code to masm format.
|I am having problems.
|Difficulty in understanding pointers, ADDR, etc.

|.686
|.model flat, stdcall
|option casemap :none
|include \masm32\include\windows.inc
|include \masm32\include\masm32.inc
|msgcnt equ sizeof msg
|.data
|msg db "I have plenty of great time because my code is short.",0
|origin dd 0
|clip_ptr db 50 dup(0)

A pointer is a dword (qword in 64-bit world), which hold an
address to a data-struct or code-label.

|.code
|
|start:
|
|do_it:
| mov ecx,msgcnt
| cld
| mov edi,byte ptr clip_ptr ;points to clipboard header

first, a pointer is 32 or 64 bits wide (mov edi 'dword prt'..)
but for windoze you need to get this pointer and the max. size
from an API-call as you have done in your example.

| cmp [edi],ecx ;first dw is max. clip_size

this first dword is in 'my' clipboard, not sure if you find
the windoze struct-layout in your win-API-help.

| mov origin,edi ;save clip_ptr
| jc done ;set carry if too large
| mov esi,byte ptr msg
| add edi,4 ;no carry to expect here
| rep movsb
| mov [edi],00000a0dh ;CR-LF and zero mark at end
| mov clip_ptr,eax ;make this string non-temporary
|done: ;ignore and do nothing if too large
| ret
|
|end start

OTOH, why store something into a global clipboard and lock it ?
As long this instance is kept alive by the OS, the string
remain in memory anyway.
Or is it supposed to work as inter-instance communication ? :)

__
wolfgang

### The unaligned bridge

I think we are now ready for programming decisions ...
All values are single precision and should be stored in an
order which fits best for 128-bit packed single instructions.

we need a few ADD-terms more often:

A12: r1+r2
A13: r1+r3
A24: r2+r4
A34: r3+r4

because no swap instructions are available we can use PSHUFD to
load a consecutive numbered r1..r4 memory image to an xmm in any
order including doubles.

MOVDQA xmm1,R1 ;keep R1..4 in xmm1 for later

PSHUFD xmm2,xmm1,90h ;bin: 1001_0000 ;r1,r1,r2,r3

PSHUFD xmm3,xmm1,F9h ; 1111_1001 ;r2,r3,r4,r4

ADDPS xmm2,xmm3 ;keep terms A12..34 in xmm2

MOVDQA A12,xmm2 ;perhaps just needed for debug yet

and so on..., the space inbetween the lines could be used
for other needed calculation to reduce dependencies.

StructDef:
align 16
R1: (all single/dword)
R2:
R3:
R4:
A12:
A13:
A24:
A34:
...

Before I continue with this style on the whole story ...
are there suggestions for doing any better ?

__
wolfgang

________________for easier view lets keep the Rn = nOhm example

### The unaligned bridge

> |msg db "I have plenty of great time because my code is short.",0 >> |origin dd 0> > |clip_ptr db 50 dup(0)> >> > A pointer is a dword (qword in 64-bit world), which hold an> > address to a data-struct or code-label.> >> > |.code> > |> > |start:> > |> > |do_it:> > | mov ecx,msgcnt> > | cld> > | mov edi,byte ptr clip_ptr points to clipboard head>r >>
> first, a pointer is 32 or 64 bits wide (mov edi 'dword prt'.>)
> but for windoze you need to get this pointer and the max. si>e
> from an API-call as you have done in your exampl>. >>
> | cmp [edi],ecx ;first dw is max. clip>si>e
>
> this first dword is in 'my' clipboard, not sure if you>find
> the windoze struct-layout in your win-API->el>.
>
> | mov origin,edi save >lip_ptr
> | jc done ;set carr> if too large
> | mov es>,byte ptr msg
> | add edi,4 ;no c>rry to expect >ere
> | rep movsb
> | mov [edi],00000a0dh ;CR-LF a>d zero mark at end
> | mov clip_ptr,eax make this>string non-temporary
> |done: ignor> and do >othi>g if too larg>
> |
> |end start
>
> OTOH, why store something into a g>obal clipboard and lock it ?
> As long this instance is kep> alive by the OS, the strin>
> remain in memory anyway.
> Or is it supposed to work as inte>-i>stanc> communication ? :)
>
> __
> wolfgang

I start my program on boot up to fill up the clipboard so I can just
do a
Shift Insert to insert the text at the end of newsgroup postings.

I don't do a lot of print screens, so the text stays in the clipboard
awhile.

Andy