Contribute
Register

Switch

Status
Not open for further replies.
Joined
Jul 18, 2011
Messages
297
Motherboard
Z77X-UP5 TH
CPU
3570K
Graphics
R9 270X
Mac
  1. MacBook Pro
Classic Mac
  1. 512K
  2. LC
  3. PowerBook
  4. SE
Mobile Phone
  1. Android
I've spent a bit of time mapping the switch PCB. Some components are yet to be identified but the ones known are provided below with their data sheets. 0Ω resistors have been omitted.

Schematic:
71447-dsc0571.JPG

Q100: 3 pin NPN SOT23 - Standard layout, no data sheet required. Pin IDs are in the main schematic

U1: TI HA14 - No such part in TI's database. Closest match is DFP HC14 hex inverting Schmitt trigger. Turns out it is an inverting Schmitt-trigger, the HC14 is just a publicly available version.

U2: Philips 87LPC762 - GP microcontroller
http://www.keil.com/dd/docs/datashts/philips/p87lpc762_ds.pdf

U10: IR 431L - LV shunt regulator (5 pin SOT23 layout)
http://media.digikey.com/pdf/Data Sheets/International Rectifier PDFs/IRU431L,AL Rev1.3.pdf

U11: No clue but it appears to be polarised

U200: NS LM7101 - LV Rail-Rail OP-AMP
http://www.smd.ru/images/upload/ru/1395/lmc7101.pdf



I also did some quick readings on the scope.

Newfile9.pngNewfile8.png

When pins 3 and 4 on the connector J1 are left open and the analog ground is left unconnected, the system goes into a sort of "idle" mode where every 8.82 seconds, the microcontroller emits a 170µs square pulse from pins 11 and 12 (shorted together).

Newfile10.png

When pins 3 and 4 are shorted, this behaviour is suppressed and instead a square wave with a 98.35% duty cycle is output when the sensor is triggered. The duty cycle gradually drops to zero when finger is removed. These two pins are therefore assumed to be configured as a PWM.

View attachment 71521

The HA14 Schmitt-trigger has the same pin configuration as the HC14 shown above. Unused inputs need to be grounded, which is why so many pins on U1 are connected to analog ground.

71537-dsc0573.jpg 71536-newfile13.png

The HA14 here has the negative rail connected to ground, which for our purposes is 0V. Therefore, the low threshold for the Schmitt-trigger is also 0V. Out of the six units on the flatpack, only three are used. The first two create the square wave and the last stage buffers and inverts it back to the correct phase before outputting it to the microcontroller's (U2) external counter pin (pin 13). The resistors and capacitor on the first stage (R1,R10,C1) set the frequency of the square wave generated. I didn't bother measuring this because the added capacitance from the test equipment would change it. I have however provided the voltage across C1 over time along with the square wave the op-amp generates from it. Notice the two thresholds at work. Once the voltage across C1 is 0V, the output becomes 3.08V and only when the capacitor is charged to 2.04V does it switch back to 0V.

71534-newfile11.png

The next stage in layman's terms, isolates the first stage from any interference that could come in from the microcontroller. However these are inverting Schmitt-triggers; notice how the output from the second stage (Cyan waveform) is flipped. To flip this back, we just need to pass it through another stage.

71535-newfile12.png

Much better. Great so what now? We have a constant square wave being pumped into the micro controller, what does this have to do with the sensor? The mentioned earlier that the frequency of oscillation was set by R1, R10 and C1. While this is true, it's mostly C1 that's the determining factor. We established that the op-amp only switches when the capacitor hits the threshold voltage. And the speed with which it reaches this threshold is determined by its capacitance (the funny value with the unit farads). It makes sense that increasing the capacitance will increase the amount of time it takes to charge to the threshold voltage. Increased time means decreased frequency.

Now consider this. Everything around you, including yourself, has some degree of capacitance. Humans make fairly good capacitors, which is probably why this circuit works as well as it does. Regardless of what electrical circuit you touch, if it's powered you will always in some way affect its function by introducing additional capacitance. This why it's recommended that you wear some sort of insulator before handling delicate components. The same thing applies to our sensor. Notice in the main schematic, the sensor ring is connected in parallel with the C1. When you bring your finger close to this ring, you in fact become a capacitor to ground; a part of the circuit. With your body added, the equivalent capacitance seen by the Schmitt-trigger increases, and therefore C1 takes longer to charge. A longer charge time entails a lower frequency. If you look at the waveform across C1 on the scope while bringing a foreign object close to the sensor ring, you'll notice frequency change inversely to its distance from the sensor.

I'm yet to determine how this frequency affects the LED, but if I was to guess, I'd say that the microcontroller looks for a certain frequency on the T1 pin (pin 13). When the signal entering is less than a threshold frequency, it triggers the light.



Updates


28/10 - Fixed stupidly placed L5 connection
29/10 - Added U1 scope probes
 
I've finally found time to play around a bit more with the button. I have been able to deduce with confidence that the frequency detection is handled in house. The output from the cascaded Schmitt triggers is passed into the timer/counter pin which is set up as a pseudo PLL in code.


I was also hoping that the sleep pulsating was done in house as well, but unfortunately isn't. I didn't have a working cube to run tests with so I borrowed a friend's MDD G4 which uses the same series MCU to handle it's front panel events. After mapping it's board I found that although the connection setup was largely the same (allowing for the lack of the free running oscillator and it's connections for the sensor), Apple had removed a lot of passives going to the MCU which would ordinarily be used to stabilize and clean up any noisy signals. For example, virtually all inductors between the connector and the MCU are missing. There are also far fewer bypass caps. Whether they found these components caused stability issues in the cube's sensor or they removed them to keep costs down, your guess is as good as mine. Oh well, worst comes to worst, they can be sucked off and replaced with shorts.


Getting back on track, after transposing the connection to the MDD, the sensor turned it on without any hassles. I put it to sleep and to my surprise, the light pulsed as it should. I was rather certain at this point that the SMC or whatever was used back then was just sending something over One-Wire protocol or something else proprietary. To test this, I probed PIN 3 (CIN1B) and put the machine to sleep again. To my great dismay, all the scope showed was the PWM signal in sync with the LED. I was rather disappointed but I remembered these machines also had ADC (Apple Display Connector, not A-D converter!) support back then and that maybe it was just a feedback line so the Cinema Display could take advantage of the same pulsating. Slim chance, but still a possibility. In order to confirm this, I needed to determine the origin of the signal. But how could I do that? The wire is virtually a dead short and on the motherboard side, the trace probably buggers off into one of the internal layers.


I came up with a simple method of doing this. It's rather crude and signal processing engineers will probably clutch their sides and gasp for air but it worked as a quick and dirty solution.


bzL0ge6.jpg

I broke the CIN1B line and passed it through a 100:10kΩ voltage divider, then probed the junction. The idea is this; if the PWM signal at the junction peaks at the circuit's 5V, then the signal originates from the device connected to the junction. If however the peak voltage reads lower {in this case, 5V * 10kohm/(10kohm+100 ohm) ≈ 4.95V}, then we can deduce that the other device is the likely source. I connected it up, put it to sleep again and unfortunately. The sensor input was reading lower, indicating the PWM control was done by the machine. When I probed the motherboard for the cube, I noticed that CIN1B went off to a rather large QFP package manufactured by Mitsubishi with the part number 'M3062MF...'. The flip side of the MDD also has the same QFP, as do a few other iMac G5 boards I have lying around. I presume this device is responsible for the sleep indicator pulse among a few other things. Most probably a beefy (for the day) MCU or CPLD. I guess that's what passed as an SMC back in the day.
 
I wanted to have a go at recreating the pulsating waveform output by the Cube. Now unfortunately I no longer had access to the MDD so I had to make do with an old MacBook Pro lying around.

Although the pulse can easily be modelled by a simple sinusoid, it doesn't give the extended troughs like the originals since the function is inherently even. Ideally, we would like to mimic the original as closely as possible. Before running at the problem head on, we should have a look at what we're dealing with.

Since the LED is controlled by a PWM probing withe LED line directly isn't going to give us anything useable. So let's setup a simple low pass filter to attenuate the high frequency sampling noise.

LPF.png

The arrangement above is a first order LPF with a cutoff frequency dictated by 1/2πRC. Since it's first order the attenuation rate isn't great (-20dB/dec) but it's fine for these purposes as the sampling frequency is well above the pulsing frequency. I chose 1kΩ and 10µF, giving a cutoff frequency of 15Hz. The filtered waveform is shown below (Filtered is cyan).

Newfile2.png

The output was clean with no noise, so I exported the data as a .csv and opened it in Excel. The moving average worked well and showed a far less noisy periodic function, but unfortunately it didn't produce the equation. No loss, the results from the scope aren't completely useless and I didn't have my hopes too high for this anyway. So onto plan B.

Two and a bit centuries ago a brilliant mathematician by the name of Joseph Fourier proposed the then preposterous idea that everything could be modelled by sinusoids. They all thought he was mad. "Really Joe, you can even model a staircase with sine waves?" But sure enough, given that you have enough, you can make these wonderful freaks of math wrap around any goddamn thing you please.

Plan B was to use Fourier's technique to approximate the unknown pulsating function. Note approximate, not find. The Fourier Series is a constructively additive method of using sinusoids oscillating at various harmonics to approximate periodic signals. The more sinusoids you have, the more accurate your approximation will become. You may have heard of an FFT function if you own an oscilloscope or spectrum analyser. FFT stands for Fast Fourier Transform and is a similar technique designed to work with non periodic signals. The Fourier Transform looks at a window of a signal and finds all the various frequencies contained within that snapshot. Think of is as a tool used to find all the ingredients used in a cake. The Fourier transform is arguably the single most useful tool in the signal processing engineer's kit. Knowing all the components that make up a signal is an incredibly useful debugging technique and is also used in many of your everyday devices. Your phone for example uses filters tuned by Fourier analysis to discard unwanted GSM bands. FM radio uses an almost identical technique to tune into specific stations. Wi-Fi, Bluetooth, NFC, RFID you name it. If it works wirelessly, you can bet your bottom dollar Fourier has his finger in it. A lot of people idolise Tesla as the ultimate badass engineer; ladies and gentleman, I present to you, Joseph Fourier.

Anyway back on topic. Remember how I said we could still use the scope data later on. Well it comes in quite handy for this. If we take a look at the measurements, we can see that with the horizontal scale set to 1s/dev, the period of the filtered waveform is 5 seconds, or 0.2 Hz. We also have a minimum voltage of 1.77V and peak at 2.23V. Therefore the peak-peak voltage of the signal is 0.46V; let's say 0.5. We can also note a change in nature at about 1.5 seconds where the signal begins declining.

Believe it or not, this is all we need to model the signal. Don't believe me? Hang in there.

Before going ahead with the calculations, I'll briefly focus on the three equations we'll need for this task. I said earlier that the Fourier Series is an additive process. Well here's the reason for that:

P1_1.jpg

This equation basically says that the unknown function we want to model x(t), is nothing but an infinite sum (n = -inf -> +inf) of exponential trigonometric functions (e[SUP]x[/SUP]) multiplied by a coefficient (c[SUB]n[/SUB]). You might be thinking, whoa... an INFINITE sum? That sounds painful. Well, recall I said earlier that this was an approximation; and the more sinusoids you have the more accurate your approximation becomes. Infinite sinusoids means infinite accuracy.

P1_2.jpg

The next two equations calculate these coefficients. OH GOD... INTEGRALS...WHY?? Yeah I know...blood, sweat and tears right? But here's the good news. You only have to calculate these ONCE. After that, you just plug your values for n in and the series solves itself. Don't worry about trying to understand these in this form because it's much easier to follow in a practical example. Now let's move on to the math! Shall we?

Now, I said earlier it was important to take note of the change in the function's nature at 1.5 seconds. The reason for this is because unlike the 1.5 - 5 second interval where the voltage seems to decline quite linearly, this portion rises at a much faster rate in a non linear fashion. One of the catches with the Fourier transform is, if you're dealing with piecewise functions that don't have a constant rate of change, you need to know a few building block functions like x[SUP]n[/SUP], sin, e, ln, log, etc. to chop and mosaic in to take the place of certain sections. This is obviously not required for simple periodic functions that have easy pieces like a square or sawtooth wave, but our waveform starts with something quite foreign.

At first, I played around with it a bit. I tried the rising edge of y = -x[SUP]2[/SUP] (a simple parabola), the rising edge of y=ln(x) + k, but settled on y = -cos(x) due to the slightly parabolic bowl just before it starts rising at the end of a period. Ln and x[SUP]2[/SUP] would have a much sharper change in direction by comparison.

Screen Shot 2014-03-01 at 1.50.23 PM.png

Having found an appropriate substitute for the unknown region, we can start on the Fourier Series. From the scope data, I decided the sinusoidal region should take up the first 1.5 seconds of the waveform and then proceed to decrease in a linear fashion until the next period. The whole period T[SUB]0[/SUB] lasts for 5 seconds, so the frequency w[SUB]0[/SUB] (omega) is 2π/5.

P1_3.jpg

That's it. Now we can plug this into our Fourier equations to calculate the coefficients. First up is c[SUB]0[/SUB] also known as the DC component.

P1_4.jpg

Note that the frequency of the cosine from 0 to 1.5 seconds is 2π/3. The linear region from 1.5 to 5 seconds is simply calculated using y=mx+c.

P2.jpg

Next we do the c[SUB]n[/SUB] coefficients. Now I did get a little lazy here because solving this integral by hand will take pages and pages and is frankly quite pointless when you can plug it into wolfram:

http://www.wolframalpha.com/input/?i=integral((-1/7(t-5))e^-(i*n*2/5*pi*t))dt

http://www.wolframalpha.com/input/?i=integral((-0.25*cos(2/3*pi*t)+0.25)*e^-(i*n*2/5*pi*t))dt

The first five coefficients I found were:

c[SUB]1[/SUB] = -0.0828-0.0602j
c[SUB]2[/SUB] = -0.0348+0.0113j
c[SUB]3[/SUB] = -0.0039+0.0119j
c[SUB]4[/SUB] = 0.0012+0.0017j
c[SUB]5[/SUB] = -0.0014-2.57*10[SUP]-8[/SUP]j (The imaginary component is essentially 0)

Here are all five shown on the same axis.

Screen Shot 2014-03-01 at 2.11.23 PM.jpg

Now brace yourselves for the inspiring elegance and beauty that is mathematics...

Screen Shot 2014-03-01 at 2.12.49 PM.jpg

Et voilà
 

Attachments

  • LPF.png
    LPF.png
    127.2 KB · Views: 229
I wanted to have a go at recreating the pulsating waveform output by the Cube. Now unfortunately I no longer had access to the MDD so I had to make do with an old MacBook Pro lying around...
A very interesting read. I actually understood most of it - haven't used my Electrical Engineering 201/202 since my college days. :D (I'm an Aeronautical/Astronautical engineer.)
 
A very interesting read. I actually understood most of it - haven't used my Electrical Engineering 201/202 since my college days. :D (I'm an Aeronautical/Astronautical engineer.)

Great fun isn't it?
 
I transferred .csv generated from the function to my arb. gen. to test but I wasn't satisfied. The dips didn't seem to last long enough. The math is correct however I think the filter I added when originally captured the waveform skewed the output a little due to loading. I probably should have passed it through a voltage follower before hand.

To try and get a longer lasting dip, I suppressed one of the higher frequency components and got something that is much closer to the real deal.

Screen Shot 2014-03-08 at 11.10.32 AM.png

The red function is the original.​

The updated shaped looked awfully familiar. A sinusoid with a natural growth and decay screamed an exponential component. It couldn't be sin(e^kx) since the frequency of f(x) is just going to shoot off into oblivion as x grows and hence be non periodic. and it couldn't be something like sin(kx) + e^kx since sine is going to essentially be sine before e^x evaluates to 1. The only form left is e^(sin(kx)). This allows the signal to be constrained to a periodic nature, while having its rising and falling edges affected by natural growth and decay. After tweaking it to the correct period and amplitude, this is what we get:

Screen Shot 2014-03-08 at 11.19.57 AM.png

Blue waveform is y = e^sin(x)

 
Now that we have a functional sleep indicator equation, how are we going to interface it with the motherboard? Since the dawn of programmable technology, hardware and software developers have quarrelled over their respective professions. Software engineers will argue that without them, there would be no intelligence to a system. Hardware engineers will rebut that without their contributions, software engineers would be out of a job. I tend to agree with the hardware guys on this since inherently (last time I checked at least) software needs a platform to be built on, but I do recognise it's limitations. There is no doubt that any processing done in software can (with correct implementation) be done faster by an equivalent hardware system. Think of an emulator vs the actual hardware. The actual hardware (using technology of the same era) will always run faster and far more efficiently. The hardware does however sacrifice flexibility in favour of efficiency, just as software sacrifices efficiency in favour of flexibility.


Why am I telling you this? Well because these are factors that need to be taken into consideration when designing platform interfaces. In our instance, we absolutely could design a system that implements our analog fader equation and put it into a simple logic circuit. This sounds great if we consider the fade controller as a black box, however consider the amount of time, frustration and cost that's going to go into designing said controller.


A fair number of RC timing blocks will need to be used to set the rising and falling regions. Voltage regulators controlled by these timing blocks (or alternatively a PWM controller IC) will need to be finely tuned to get the output voltage margins just right. The system quickly becomes a hairy beast not to mention the increased size, and there’s no guarantee you’ll be able to get the exact output modelled by your equation (if precision is important). A hardware solution is a laugh when you can pick up for less than a cup of coffee, a micro controller that can do the same thing better in less time.


Enough with the lecture let’s jump to the good stuff. Our implementation using a micro controller greatly simplifies things. If we consider the system as a black box again, all we have is two lines coming from the motherboard for the Power/Sleep state indicators, a line going out to power up the motherboard and of course Vcc and GND for power.


IMAG0150 copy.jpg

Peering a little further into the black box we see that the Cube’s sensor interfaces with the micro controller using a single wire, which controls the LED’s instantaneous brightness. How simple is that? The rest is all software.


IMAG0150.jpg




Motherboard State Detection


Practically all motherboards today come with support for both a power and S3 sleep indicator. Some front panel headers have discrete pins for each. Some use a ground toggle approach whereby the system will toggle which of the two pins is high/low. At the very least, some systems will flash the power LED while in S3. So how do we translate this into something the micro controller can understand?


The first implementation is simple. Since there are two discrete headers for power and sleep, the lines can be linked to the micro without anything fancy. It’s good practice to put in some current limiting resistors but there’s almost always over current protection included so it’s not a necessity.


IMAG0147.jpg

The second approach has a few more components. Since there’s only one header used for both states, we need to detect which pins are high/low at any given point. This can be handled with a simple diode on each of the outputs. It’s also a good idea to pull down the micro controller input to ground so it’s not floating. A nice round 1kΩ will do the trick.


IMAG0148.jpg

A flashing sleep indicator is implemented probably the more annoying of the three. Since there output of the pins is not binary, an ADC will need to be used to distinguish between the states. So how does this work? Well, think of the flashing LED as a very slow PWM signal. Assuming the indicator flashes on for (say) one second and off for one second, the signal has a duty cycle of 50%. If we low pass filter this output, we would expect the analog voltage to be (ideally) 50% of that driving the LED. This of course will change depending on the loading effect introduced by the filter. It’s probably also a good idea to buffer the output from the LPF with a voltage follower.


IMAG0149.jpg


All that’s left now is to set the ADC thresholds programmatically. If we expect 2.5V in S3 sleep and are using an 8-bit ADC, we would trigger sleep if the ADC reads ≤127. You can play with this value to tune it specifically for your system.




Note: The values of R and C will be determined by the frequency at which the LED flashes. Use the formula f[SUB]cutoff[/SUB] = 1/(2πRC)


With the detection circuit complete, all that’s left to do is implement the software. This will just be a series of conditions constantly being checked in a loop. In pseudocode it would look something like this.

Code:
[COLOR=#232323][FONT=Verdana]
[/FONT][/COLOR][COLOR=#232323][FONT=Verdana]initializeIO();[/FONT][/COLOR][COLOR=#232323][FONT=Verdana]
initializePWM();[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]initializeADC();        // if needed[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]
[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]while (1) {[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]
[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]    getADCValue();     // use if needed[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]    getIOState();    // use if there are discrete pins[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]                // These will set either sleeping or awake to true, depending on the system’s state[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]    if (sleeping) {[/FONT][/COLOR]

[COLOR=#232323][FONT=Verdana]        pulse();[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]    }[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]    else if (awake) {[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]
[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]        setLEDtoConstantValue;[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]    }[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]    else {[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]
[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]        ledOff();[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]    }[/FONT][/COLOR]
[COLOR=#232323][FONT=Verdana]}[/FONT][/COLOR]

 
Nicely done! I'm glad it was of some use and not just waffle.
 
Status
Not open for further replies.
Back
Top