Archive for Projects

Sure, we’re brute-forcing, but what’s the rush?

Ironically, in the process of writing a really fast implementation of the WPA2 encryption scheme, it was necessary (or at least easier) to first write a really slow implementation.

Here is my wpa2slow Python module.

To be fair, the actual speed at which this hashes isn’t the point. The point is that I have an entirely native Python implementation of how the entire WPA2 algorithm works, with an emphasis on code being clean, easy to read, and forgoing any speed optimisations that hinder legibility. Judging from the quantity of misinformation I’ve seen while researching this topic, someone will find this project useful. A lot of people have been having trouble trying to fit all the pieces together, over the years.

At first, I included the pieces as mock objects for unit testing. Each of the pieces (SHA1, HMAC, PBKDF2, etc) were built up over a period of several months, vaguely mimicking the interface format of equivalent existing hashlib libraries. Unfortunately, all of the standard Python hash libraries are really inconsistent!

For example, to hash a string with SHA1, I’d use:

output = hashlib.sha1(str)

Makes sense. But to then hash it with HMAC-SHA1, I’d do:

output =, value, hashlib.sha1)

Which is pretty weird, in this context. It makes more sense when you realise that HMAC can work with multiple sub-algorithms (commonly SHA1 or MD5), and you can go multiple rounds with adding more salt. That’s not the case in my implementation, however, so copying the format was a mistake.

One thing that rests solely on my shoulders is the massive amount of debugging information, hacky fixes, and generally poor code I’d written while focusing on an entirely different problem.

If I had written it cleanly from the beginning, it would have been a lot less work, that was silly of me.


Anyway. It’s pretty decent now. Check it out, read the docs, or install it!

pip install wpa2slow

ReacTick R1.5

Prototyping aw yeah.


After the first version of my LCD widgets, there were some things that I was planning on changing for the next respin. R1 just to get some hardware in my hands and start writing code. This next one is all about the cleanup.


The last version of R1 is here on GitHub. It works… Poorly. The code in the test folder is stuff to help me prototype, before I got to a working model. Originally, I tried writing an LCD driver in Python for the Raspberry Pi GPIO, but the output seemed super unreliable. Instead of taking the time to troubleshoot why, it was faster to port that code onto a PIC dev board, which worked great.

Once I had a known-good LCD (using the shift register), I finished soldering up the rest of the board and tried to bring up the whole board. It never quite worked properly, and here’s why!

When I was first drawing my schematic, the most common ESP8266 module was the ESP-12. Right around that time, November of 2015, the ESP-12E had just come out, with a bunch of extra pins. No one knew much about this at the time, but the conventional wisdom suggested that it was safe to include them in my design, allowing me to get away without using an additional microcontroller. Turns out these extra pins are associated with the flash memory, and using them willy nilly causes strange reset issues. Guess what kept happening when I was trying to test my fully populated board?

So before a complete rethink was in the cards, here was the original plan for revision 2:

  • The LCD has two little mounting tabs on the sides. An appropriately sized via to accommodate them will make the LCD fit better and prevent wobble
  • One of those mounting holes will interfere with the switches. Move them somewhere else. Specifically on one of the short edges, because the current location causes damage to the LCD when the buttons are pressed while the screen is face down on a table
  • Silkscreen for momentary switches to include functions (RST / PROG)
  • Add in the clever circuit that the NodeMCU group uses to enable button-less programming
  • Remove all unnecessary resistors:
    • R7 connected to LCD_RST
    • R10 connected to LCD_RS
  • Change LEDs to 0805 or something similar. I’m using 3528s, and they are huge and super bright and look out-of-place
  • Change user-settable LED to connect to a pin that is not GPIO16. Apparently some manufacturers (not mine) connect it internally to the ESP8266 reset pin
  • Change all the SIPO shift register pins from bit-banging to use the ESP serial ports – Should be faster, and allows me to…
  • Change requirements from an ESP-12E module to just and ESP-12, which has fewer pins
  • Break out extra ESP pins to some unpopulated pads for future hacking
  • Break out LCD touchscreen pins for future hacking
  • Add more testpoints for debugging (and future hacking)
  • Big decoupling cap


Some of these ended up making it in, but the new system design deprecated other points. So what’s new in R2? Stay tuned to find out!

R2 Paper

Unpacking WPA2

As discussed in a previous article, WPA2 encryption is comprised of three different algorithms layered on top of each other. I went over them in a very brief overview, so here is a more in-depth discussion on how I optimised and implemented them on an FPGA.

Also linked in that previous article, it’s worth going back and reading this presentation again. It really is a great overview of each of the three algorithms and how they fit together, without muddying the waters with the low-level details.

Disclaimer: This is my process for understanding and breaking them down. I will be using non-standard terminology, and there are certainly other ways of internalising these algorithms. My methods aren’t the only methods.

The lowest building block, SHA1, has four distinct sections stages of note: Load, Process Load, Process Buffer, and Output.

In a completely linear implementation, it would look like this:

SHA1 Linear

I’m assuming a bus width of 32 bits. The input/output blocks on the end are fixed in size, and cannot overlap. Not if we want to maintain half-duplex compatibility with the parent device. That may or may not be important, but it sure does simplify the implementation for now. 165 clock cycles total.

We have a little more wiggle room with the red blocks. Because the buffer can be processed as it is getting populated by the Process Load stage, we can merge them. Extrapolated, and using the input/output as the bottleneck, we come up with this:

SHA1 Parallel (2)


Notice that there’s still only one green section running at any single point along the horizontal. That’s the critical path, and dictates how many parallel operations we want to run at once.

It works out to 106 clock cycles for one cycle, assuming we run 5 hashes in parallel. So, 22 clocks per hash. Way better.


The next block up, the HMAC function, contains two SHA1 functions, which is sort of annoying. The second/outer call is also dependent on the output of the first/inner one, so I can’t parallelise that at all. To fill up the 5 SHA1 operations I have going at a time, I must also be running 5 separate HMAC operations.

There is one optimisation to be done, though, mentioned in the presentation. It’s not obvious how it’s useful in a concurrent environment, but bear with me.

Part of the algorithm requires two buffers to contain the ‘secret’ portion of the HMAC input, padded with 0x36 or 0x5c up to 64 bytes. The parent algorithm, PBKDF2, iterates two HMAC functions, 4092 times, all with the same secret variable. That can be calculated once and used for the entire loop.

If everything is done in parallel, then one would expect that the calculation could be done on-the-fly with little to no penalty. When you consider that each round of SHA1 is 64 bytes, however, you realise that a padded 64-byte input message, followed by the ‘secret’ variable requires two complete rounds of the SHA1 function to come up with the final result. But the first round of SHA1 results in the same output, every time, and can be precalculated. This turns the HMAC algo from what is effectively four SHA1 operations into only two.




Note that they’ve actually written this algorithm incorrectly, there is an additional XOR to combine each stage of x1/x2 into a final result, but no matter for this discussion.

The PBKDF2 part is by far the most expensive step, because the area of most FPGAs will be too small to unroll 8192 copies of the SHA1 algorithm (which requires minimum (80 words * 4 bytes * 8 bits = 2560) bits of buffer space). One more optimization could be done, given the right conditions, and it’s a doozy:

The final, very last operation in the whole mess is to append x2 to x1. No hashing after that. That means the final output is two groups of 5 words (40 bytes total). This is the Pairwise Master Key. It is statistically unlikely that the first 20 bytes will be correct, but the second group would be wrong. This means that if we have the PMK and only need to verify it, we can do these calculations with exactly half the silicon area, or twice the speed.

Unfortunately, in this particular use-case we don’t have it, but it’s a great trick to keep up our sleeve.



So what do we have in this use-case?


We’ve gone from the wifi SSID and passphrase, known as the master key (MK), and from that, generated the Pre-Shared Key (PSK), which is known as the Pairwise Master Key in this particular implementation of the PBKDF2 algorithm.

To verify the PMK against the passphrase, something called the “Pairwise Key Expansion” is calculated. From the captured WPA2 packets, we have a few variables: client MAC address, AP MAC address, client nonce, AP nonce, and the Message Integrity Check (MIC), packet body.

The first four variables, along with the PMK get combined together in kind of an annoying way, and then compared against the MIC.

They just call it the pseudo-random function (PRF), and it goes kinda like this:

a = "Pairwise key expansion";
b = min(APMac, CMac) . max(APMac, CMac) . \
    min(APNonce, CNonce) . max(APNonce, CNonce);
r = "";
for(i = 0; i < 4; i++) {
    r = r . HMAC_SHA1(PMK, a . "\0" . b . chr(i));
return r[0:64];


Yeah, the actual string is used in the PRF.

This gives us the Pairwise Temporal Key (PTK), which is then combined with part of the (encrypted) body of the packet we captured:


mic = HMAC_SHA1(ptk[0:16], data[60:121]);


And then compare this to the MIC we’ve already captured! Easy, right?

No! It’s a huge pain and would add another HMAC_SHA1 block that we don’t really have room for. This will probably be implemented on the microcontroller firmware or the host software of my system.

Reconfigurable CNC platform

I’ve got a big thing about building stuff in a modular way.


So I installed Fusion 360 yesterday, and I’m pretty impressed. Fusion 360 is a new SolidWorks competitor by Autodesk. Basically a $6k-8k CAD package, released free for hobbyists or businesses making less than $100,000 a year. That’s quite a hook.

Especially considering how good it is already. It’s not quite at par with SW, but the feel is very similar, and I can see it eventually being a strong contender. Plus, you know, free.


The parametric engine is also very good. I’ve been meaning to build a CoreXY platform for a long time. It’s an open source belt-driven CNC platform with balanced forces in the X and Y axis, an excellent build-area / platform-size ratio, and parts that are amenable to laser cutting. There isn’t a specific project it will go with, but you never know when you need to drop a CNC system into something. CNC everything!

The idea behind building it is that I’d like to be able to design and build a platform to conform to whatever my requirements for a specific project within about a day or so. There are a few major variables that could potentially change:

  • Motors
  • Belts / pulleys
  • Precision rod
  • Material thickness

I’ve already purchased belt and pulleys ($10 for the cheapest GT2 belt, $10 for matching pulleys), and ideally, I’d be able to use the rest of those common items that I have kicking around, or can scavenge easily.

So I redesigned the CoreXY platform entirely using variables and formulae. Based on the waterjet cut CoreXY. Here’s a list of the variables that you need for a CNC, apparently:

CoreXY VariablesThat’ll change a little as I continue tweaking.

All other measurements are derived from those. Now when I need a new system, I take stock of the motors, sheet material, and so on, and enter the values into the window. A laser cutter file magically appears on the other end.

Here’s my project. It’s definitely subject to change. Accounting for laser cutter kerf is on the roadmap, and waterjet cutting would be good to design for, too, although I’m not super familiar with the constraints on that.


The files are located in the cloud right here. The X carriage is coming in a few days when I’ve got a few minutes. This is also part of an ongoing project documented in this Vancouver Hack Space thread.


One thing that I had problems with, is that Fusion 360 is not capable of reading parameters from subassemblies or parent assemblies. I had to copy the same set of variables to all of my parts, which is pretty annoying. Some internetting says that this feature will be implemented Real Soon Now(tm), as of 2014.


A good help for that was an add-in called ParameterIO. It doesn’t work out of the box, though, there is a bug because of the dimensionless quantities in linear patterns.

I had to edit line 219 of:

To say this:

unit = ' '
     unit = _param.unit
     unit = 'FUCK'
 result = result + + "," + unit + "," + _param.expression + "," + _param.comment + "\n"

(The swears weren’t necessary for correct operation, but they sure made me feel better. Full file here for easier copying.)


That allows you to export all of the user parameters, and also the model parameters as a CSV file. The same bug causes problems when you try and import!

Fortunately you can delete the second half of the CSV file before importing, because the model parameters are a useless thing for unrelated parts.

An add-in to automagically inherent all parameters from parent assemblies would be awesome, and fairly straightforward, from the looks of things.

Maybe this feature already exists and I just haven’t found it, or maybe I will have to work on it when I’m done the X axis of this thing.

I don’t lamp well


That was a long “next month”. A recap is in order. This post chronicles the long descent into complete and utter apathy.


In September 2014, I made some sketches for a lamp I wanted to build. The intent was to use the glass plate from a desktop scanner as the light diffuser, and laser etch a fractal pattern onto it to create a frosted effect, instead of being optically clear.

Here is a test piece I did, with a laser cutter and an image found off the internet.



The results were pretty fantastic. Fine details get lost, because it looks like the mode of operation is the laser heating up enough of the glass to chip off a small chunk before moving on. And so on, for the entire image. It creates great looking, even optical diffusion, though.


For another test, I decided to design and build a similar, but smaller lamp. Glass scanner beds are a limited supply. Using a glass tile I found at a craft store, I designed an arm to hold it onto a wall, a few centimetres away from a PCB containing some high power LEDs.



The initial model and 3D print is shown on my previous post.

Here is the final version, with some corrected measurements and better mounting point.

Lamp print


And the PCB arrived shortly after the last post.


Lamp PCB


That’s mistake number one. Everything was intended to be clean and white, but I guess I forgot to change the soldermask from the default DirtyPCBs red. It’s not the end of the world. This is a prototype of a prototype, after all.


The first board was populated, and then the lamp languished for a year and a half.



Recently, I found it buried in a locker and tried plugging it in for the first time. With no prior consultation to documentation, I tried it on a bench power supply, starting at 5v. Nothing happened, so I turned it up to 10. At 15v, the semiconductor on the board released some smoke and glowed red for a few minutes.



Back to the docs, I read that I had used an adjustable 5v boost converter, so that solved that.

I soldered up another board (I had two spares of the IC), including the DC barrel jack this time, and plugged it in again. Turns out I had the wrong polarity!

No smoke, but some troubleshooting proved that I had definitely fried the chip.


This was pretty much the limit of how much I cared, so I did what anyone would do:

I jumped over the active parts of the circuit with a power resistor, and ran the LEDs directly from a 19v laptop power supply.



Job done!

Next time I’ll build in some more safety factor.

Additionally, looking at the lamp from the side is really really bright because of the bare 1W LEDs. I kinda planned for this and put some slots in the side of the base for some acrylic sheets, but I’m quite done with this design.

Snap-on Desktop Widgets

And now, for my next trick, I’m going to manufacture a million tiny monitor widgets to snap onto your big monitors to monitor your widgets.


Still with me?


This is a project with many parts, but I will only get in to one phase on this log.


I’m hooking up an ESP8266 WiFi module to an inexpensive TFT LCD. The idea is to have an internet-connected, smaller-than-credit-card sized screen that displays one thing, and one thing only.

Some use-cases could be the two-day weather forecast, a slideshow picture-frame, or a graph of the current price of Bitcoin. Things that don’t require more than a couple changes per second, and don’t warrant using up real estate on a main monitor when work needs to get done.

The system design is actually really simple. A mini-USB connector is feeding power to a 3.3v linear regulator, and data to a USB-UART bridge. The bridge is able to program the ESP8266 via USB to a host computer, but that is not required for general operation. A standard cellphone charger plugged into the USB connector for power is fine. The WiFi module connects to an Access Point periodically and grabs a static image from a website.

This image is then fed to the LCD. That’s it. That’s all it does. I’ve gotten the BoM cost down to around $8 each, so it’s reasonable to have a lot of them on a desk, displaying various bits of data.


The hardware files, including Gerbers, of revision 1 are here. There are also folders for the firmware, software, and test rig, but as of the time of writing, that is all very much a work in progress.

That link will soon be outdated, but I’ll tag the first revision as a “Release” in GitHub when I’ve got the different parts working.

As for next steps:

The LCD I’ve chosen is one of the cheapest ones I’ve found. It has a parallel data bus for communication, and I’ve used a 74HC595 serial-parallel chip to make it work with the ESP8266 module’s limited IO. I’m using an ESP-12E for reference, but trying to make it work with the original ESP-12 as a bonus.


I think I can do some interesting things by replacing both the SIPO and the USB-UART bridge with a microcontroller. Things involving bootloaders, and things involving cross-monitor communication. Cool stuff.


After building my Piccolo and playing around, I really don’t like the software. It’s certainly simple and hackable and does a lot of what I need to do, but something about the Arduino/Processing pair don’t quite work for me.

Fortunately it’s just a bunch of servo motors, and I already have the PIC code in my toolbox.

Using my Arduino-form-factor PIC dev board and my Bus Pirate as a computer-UART bridge, I wrote in a simple protocol to communicate.

The “communication enable” pin will go high, and then two (might change to three) bytes get sent. The first is an “address” or command, and the second (or second two) bytes are a value/argument.

The 0 address is X axis, 1 is Y, and 2 is Z. The Z only uses binary 1 and 0 for arguments.

The z axi has two states: active and inactive. Inactive/up is the parked position, obviously. The active mode has a hysteresis loop attempting to control the position. The feedback is wired up to a window comparator, like so:

On the computer side, I’m controlling the Bus Pirate with a Python script that feeds it one scalar for a given axis at a time.

The speed at which the PIC executes the movement is controlled in the processor, to be tweaked. I will probably add that command in, when it becomes cumbersome.

As more commands become necessary, I’ll be adding more to the processor, I guess. Maybe eventually I’ll implement a rudimentary G-Code.


Now for the fun part:


Part of my original design goal was to have a 10ns response time. That’s very fast. Most of the old monolithic MOSFETs I’m using (because they’re cheap) have turn-on times in the tens of microseconds.

That totally blows my requirements out of the window, but there are still some optimizations to be made. By using analog circuitry, I can directly control certain parameters and speed them up, compared to hitting a microcontroller and being a slave to a clock source and interrupts getting in the way.

I’ve designed a window comparator. It looks like this:

Window Comparator

If the input goes above the “HIGH” voltage, then the top output turns on. If it goes below the “LOW” level, then the bottom output turns on. There will be two of these circuits. Feeding these outputs to some discrete logic, or something clever that I haven’t thought of yet, I can turn on or off transistors to the different power stages.

EDM Schematic V2

There are three power stages: Stage 1 (rectified input), stage 2(charge), and stage 3 (output).


The S2 MOSFETS can be ignored, just treat them as one. I should be able to parallel as many as I need, within reason, it doesn’t change (most of) the math.


The input of one window comparator is from VOUT, and the outputs are hooked up to the micro. If the HIGH output is on, then that means the MOSFET Q2 is on, but the EDM electrode has not made contact with the workpiece. Start (or continue) jogging the Z axis down.

If the LOW output is active, then we’ve gone down too low, start jogging up.

The other comparator’s input is at S2VCC. That controls the turn-on and turn-offs of the MOSFETS. If C3 is too low, then Q2 must be shut off and Q1 turned on to charge it up. When it is high, flip that. The idea is that Q1 and Q2 should never be on at the same time, providing a direct path to ground. The logic here will also involve halting the Z jogging, or making it jog up.


So there you go. With two different kinds of hysteresis going on at once, there will be some experimentation going on with how they work together. That leads me to one last trick:

You see the HIGH and LOW inputs on the comparator circuit? Those must be an analog voltage. That I’m going to set with a PWM out on the micro and the caps smoothing it out to an analog value. Varying the duty cycle of the PWM will allow me to vary the analog voltage.


Counting up my PWM outputs:

Two for each window comparator (4 total)

One for each axis (7 total)

One for the oil pump (8 total)


I haven’t discussed that last one yet, but stay tuned!



Aw yeah, CNC day.

CNCed Tank

Pretty simple parts, I guess it wasn’t strictly necessary to use a CNC, but hey, it was there.


Here it is coming together.

Tank Test Fit


A spaceship!

CNC Spaceship



Brief interlude




Laser cut Piccolo parts.


Piccolo Assembly


And the rest of it.

Piccolo Assembled

Rough-ish final box.

Small EDM Tank

And it flips up!

EDM Tank Up


So the next step is to figure out a way to mount the Piccolo on top of the box as shown. There’s a little bit of MDF I need to cut away to make it fit better, too.


After that, I need to modify the Arduino sketch (ugh) to jog the Z-axis up and down to keep the electrode in the conductive region.


Hell yeah, acronyms.

Restartin’ dis.

I’ve got the old working SHA1 encryption algorithm going. It’s up on GitHub, here. I was waffling between parallel and serial loads and outputs. SHA1 takes a 512 bit input and outputs 160 bits, and no FPGA that I have access to will have that many pins.

Here’s a fallacy I got stuck on for a while:

If I use completely parallel I/O, it’s faster. Therefore, I should try to use as much parallel communication as possible to maximise speeds.


The truth is, though, that most modern high-speed circuits use serial data. When you’re clocking at very high frequencies, propagation errors become very difficult to mitigate. With many data lines, you have no way of knowing when exactly data arrives at the lines. It’s better, easier, more reliable to just send one bit at a time and pump them through really fast. That’s a core principle of pipelining; you don’t even need to wait for a signal to reach its destination before you’re sending the next one.


With this project, I don’t think I can go faster than 100MHz with the FPGAs I have. That’s right on the edge of where efficient pipelining starts to matter, so I’ll be experimenting with a mix of serial and parallel interfaces to see how far I can stretch it.


Right now at this moment, though, I want to get the computationally-intensive parts of the WPA2 protocol offloaded to the FPGA. I won’t worry about speed juuust yet.



Here’s how WPA2 works, from a security analysis perspective:



Some definitions


  • Access Point (AP) – Usually the router, in these systems
  • SSID – AP name. This is the router name that you connect to
  • Master Key (MK) – AP password. This is the key we ultimately want to find
  • Pairwise Master Key (PMK) – This is the cryptographically hard part of the whole transaction. It’s derived from the MK and SSID
  • Pairwise Transient Key (PTK) – The cleartext portion of the authentication to verify the correct PMK
  • PBKDF2 (wiki, RFC) – Password-Based Key Derivation Function 2 – A cryptographic function, used like PBKDF2(PRF, Password, Salt, c, dkLen) where PRF is any given hash function, c is the quantity of iterations, and dkLen is the output length
  • HMAC (RFC) – Hash-based message authentication code – Intermediate function applied to the SHA1 hash
  • SHA1 (RFC) – Standard hashing function. Uses a one-way algorithm to generate non-reversible output


The AP has the password, from which it can derive the Pairwise Master Key (PMK). To verify that both sides of the transaction have this, a PTK is generated using the PMK and nonces (randomly generated, one-time-use numbers).

This PTK is transmitted over cleartext, and is part of the 4-way handshake.


So, in short, if you combine the proper PMK with the proper PTK, the whole conversation breaks wide open and you can associate with the AP.

If you’re watching the WPA traffic, then you can easily capture the 4-way handshake and therefore the PTK.


That means that, for my purposes anyway, the PMK is the important unknown variable, and the computationally hard part. Here‘s how you calculate it, from top to bottom:


x1 = HMAC_SHA1(MK, SSID + "1");
x2 = HMAC_SHA1(MK, SSID + "2");
f1 = x1
f2 = x2
for(i = 1; i < 4096; i++) {
    x1 = HMAC_SHA1(MK, x1);
    x2 = HMAC_SHA1(MK, x2);
    f1 ^= x1
    f2 ^= x2
return f1 + f2;



This is more complicated. Given HMAC(secret, value)

  •  Initialise two 64-byte variables, Bi and Bo with secret, padded with zeros on the end
  • XOR each of byte of Bi with 0x36, and XOR each of byte of Bo with 0x5C
  • Append value to Bi
  • Append SHA1(Bi) (in Ascii!) to Bo
  • Return SHA1(Bo)

In short:

HMAC_SHA1(s, v) = SHA1((s ⊕ 0x5c)||SHA1((s ⊕ 0x36)||v))


And finally, with the SHA1 function, I have covered it in previous posts. This portion is already done.

First Burn

During my research on how others have handled the sparking circuit in an EDM, I’ve been fairly unimpressed. Off the top of my head, there was one 555-based pulsing EDM circuit, one purely analog circuit that was never built, and one hand modulated system attached to a drill press.

It’s hard to tell exactly what will make a winning design, so I’d rather not hamstring myself with fixed logic that may or may not be ideal. And for the first few iterations will almost certainly fall on the “not” side of that line.


What I’ve settled on (and indeed, what my education is in) is computer control. Small microcontrollers have gotten fast and cheap enough that there is very rarely a reason not to use them, other than bragging rights or very high volume manufacturing.


That’s a little bit unfortunate in some cases, but it’s great for this one.


Here’s a first third draft of the circuit I’ll be using. I had a few false starts, but this one is the first one I actually (mostly) drew out, and it seems to work. I used two power supplies in series to get 60V and breadboarded it up. Not the final 80V supply, but close enough.


I only simulated the first stage (and with the wrong optocoupler!) but it proved the concept.


So I got my first burn last week to prove the concept! I tried to get a picture of the sparks, but it was tricky with my crappy phone camera. I was totally welding wires together, though, it was awesome. In theory, that shouldn’t even cause excess wear on my components or power supply. Everything is well within spec.

First Burn


I’m a little but worried about the speed of my components. I’d like to be able to get this pulsing in the 20ns range, but I’m pretty far away from that, I believe.

The two important components in this are the H11D3 optocouple and the IRF9540 P-Channel MOSFET.


According to the datasheet, the transistor has a rise time of 73ns, which right there blows my timing requirements. It has a turn-on delay of 16ns which also isn’t fantastic. That’s 100ns just for the transistor.


The optocoupler is worse, however. About 5 us. I’m not familiar enough with them to know if that’s a good value or not, but I’ll look at my options for rev 2.

Worth noting that this has a base connection, which doesn’t seem to make sense, given that the optical input is basically the base.

From here, though:

It looks like it’s to my advantage to use the base! It’s floating for now, but I’ll tweak the values to get to the most out of it when I have a scope on it.