I'm going to keep it at a high level (not explain line by line, just hit the big points).
The firmware initializes and then listens for messages from the PC (either on the parallel port which is actually i2c over the pins on the parallel port, or serial port depending on the status of the PAR/SER pin).
The format of the is a single byte command (PC to PIC) with a single byte response (PIC to PC) and then the message either PC to PIC or PIC to PC.
The commands are as follows:
Configuration Send
------------------
PC to PIC: CONFSEND (B'11111001' or D'249') (one byte)
PIC to PC: Response (B'11011110' or D'222') (one byte)
PIC to PC: Buffersize (two bites, currently always D'256')
PIC to PC: ConfigLoc1 (one byte)
PIC to PC: triggerDelay1:triggerDelay2:triggerDelay3 (three bytes)
PIC to PC: sampleRate1:sampleRate2 (two bytes)
The PIC then waits for the next PC command
Configuration Receive
---------------------
PC to PIC: CONFRECIEVE (B'11111010' or D'250') (one byte)
PIC to PC: Response (B'11011101' or D'221') (one byte)
PC to PIC: ConfigLoc1 (one byte)
PC to PIC: triggerDelay1:triggerDelay2:triggerDelay3 (three bytes)
PC to PIC: sampleRate1:sampleRate2 (two bytes)
The PIC then accepts the configuration and samples the waveform accordingly
Data Send
---------
PC to PIC: DATA (B'11111000' or D'248') (one byte)
PIC to PC: Response (B'11011100' or D'220') (one byte)
PIC to PC: 256 samples (256 bytes)
PIC to PC: dataConfig (one byte)
PIC to PC: channel1offset (always D'0') (one byte)
PIC to PC: channel2offset (always D'0') (one byte)
PIC to PC: triggerLevel (one byte)
The PIC then waits for the next PC command
To sample the waveform, the PIC sets up the appropriate configuration and either start sampling immediately (in the case of no trigger) or sets up the trigger interrupt and loops indefinitely waiting for a trigger event. The PC can interrupt the PIC while it waits for a trigger by sending a Break Trigger message.
Break Trigger
-------------
PC to PIC: BREAK (B'11110011' or D'243')
PIC to PC: Response (B'11011100' or D'220')
This allows the user interface to continue to be responsive.
After the trigger event occurs, the PIC waits a time specified by triggerDelay1:triggerDelay2:triggerDelay3 and then selects the frequency sample mode based on configLoc1 and samples all 256 samples according to the mode. I'm going to address a common question. If you look at the interrupt routine, you will notice that I do not save the program context and I do not return from the interrupt. This is because I control the interrupt enable bit so that the interrupt only occurs when I am listening for a trigger event. The side effect is that eventually the PIC overwrite the eight address stack, however there are no ill effects because I do not pop the stack (unless I've pushed the stack again). For more on this, check out ww1.microchip.com/downloads/en/DeviceDoc/33023a.pdf section 6.2.5.
After all samples are gathered, the PIC awaits the next PC command.
Conversely, the PC operates on a timer (variable set in the program, defaulting to 10 Hz refresh rate). The code that executes on the timer gathers the last set of samples, updates the PIC configuration, and then redraws the screen. While it redraws, the PIC is sampling.
Now, I'm going to describe the configuration bytes:
configLoc1:
-----------
bit7: triggerslope, 1 is positive slope, 0 is negative slope
bit6: trigger enable, 1 is enabled, 0 is no trigger
bit5: clockfreq, 1 is 20 MHz, 0 is 4 MHz (this is always 1)
bit4: channelbit, 1 is channel 2, 0 is channel 1
bits 3 thru 0: frequency mode, described below.
frequency mode:
0: 1 MHz, single channel
1: 833 kHz, single channel
2: 625 kHz, single channel
3: 417 kHz, single channel
4: 250 kHz, single channel
5: sampledelayed, single channel, sample rate is 5e6/(18+7*sampleRate1:sampleRate2+3*sampleRate1
6: 5 MHz, equivalent time sampling, single channel
7: 2 MHz, equivalent time sampling, single channel
8: 417 kHz, dual channel
9: 250 kHz, dual channel
10: 192 kHz, dual channel
11: sampledelayed, dual channel, sample rate is 5e6/(26+7*sampleRate1:sampleRate2+3*sampleRate1). channel2 is sampled 1.2 uSec after channel 1.
12 thru 15: unused/invalid
Note: equivalent time sampling is expected to be used with the trigger enabled set.
triggerDelay:
-------------
cycles = a + 3*triggerDelay3 + 770*triggerDelay2 + 197122*triggerDelay1
t = cycles*4/20e6
For the equivalent time sampling, a = 23
For all other sample modes, a = 14
dataConfig:
-----------
bits 7 thru 6: Channel 1 gain. B'00' = 1, B'01' = 2, B'10' = 5
bits 5 thru 4: Channel 2 gain. B'00' = 1, B'01' = 2, B'10' = 5
bit 3: Channel 1 coupling. 1 = AC. 0 = DC.
bit 2: Channel 2 coupling. 1 = AC. 0 = DC.
bit 1: Unused, set to 0
bit 0: Unused, set to 0
I will share that some of these things are going to change in future releases to allow for feature additions, but this applies to version 1.2 of the firmware.
I hope this was helpful.
Jonathan