I don't know if anybody spotted yet the TL431-based adjustable voltage reference. Looking at the resistance divider for the 2.5V output, the output of the 74HC00 should be at (2.5Vpp*650Ohm)/500Ohm = 3.25Vpp which is compatible with the 74HC00 datasheet for recommeded operation and also makes sense to power with 4xAA batteries. This is though not good for PIC operation at 16Mhz so the replication of the Hameg's output stage is not an option with PIC driven oscillator.
Not a problem. If you need to run the output buffer at about 3.3V, make sure the regulator's feedback input is ground referenced, then simply use 2 silicon diodes after the adjustable regulator to drop the output voltage and take the feedback from the 3.3V rail. The PIC can be powered by a minimum of 4.5V, probably somewhere between there and 5V. The logic level mismatch can be easily handled with a potential divider with a few pF of capacitance across the upper resistor, tweaked to be slightly underdamped for best risetime.
Alternatively, just use a PIC that's rated for 3.3V operation at 16MHz. A 14 pin PIC16F1823 would be a good candidate and the extra I/O pins could simplify frequency selection, or if we are sticking to shoehorning it into to an 8 pin PIC then use a PIC12F1822. We could also use the Reference Clock Module, routed through the Data Signal Modulator (as its default output is on OSC2) to concurrently output a 1MHz reference clock - or any other binary divisor of the crystal frequency down to /128.
I could probably also tweak the PIC12F683 code to run with an 8MHz crystal and still output 1MHz. I'd need to change all the PR2 constants (integer divide by 2), and add code to right shift the duty cycles before loading CCPR1L and dump the original LSB into CCP1CONbits.DC1B1.
So, speaking of pin economy, in the PIC12F683 we have ...
...
... 3 pins for UI. Enough to build all 8 frequency combinations but we would need 2 other pins:
- 1 pin to turn the device on (INTx)
- 1 pin to drive the other parts of the circuit on (voltage reference and output stage)
Am I missing something?
If the output stage uses the 74AC14 we could use one of the spare inverters to build a https://en.wikipedia.org/wiki/Pierce_oscillator and provide external clock to the PIC effectively gaining one pin (would cross -talk in the 74AC14 actually be a problem?) but still 1 pin would be missing.
The alternative suggested by Ian.M is to drive an ADC pin (ANx) with a resistor ladder and some sort of rotary / linear switch to represent different UI settings. This would free up 2 pins.
You can get cute and read a digital I/O pin as High/Low/Floating - it needs a small cap (few tens of pF) at the pin to hold the state + a series resistor to the moving contact of a SPDT center off switch. The strategy is to read the pin, then briefly make it an output and pulse it to the opposite state - if it stays there long enough, the input is floating. If it is floating, make it an output until you poll it again to avoid floating pins increasing power consumption. Two pins would give nine possible combos. Together with freeing up GP4/OSC2, that would give you the extra input (only) pin - GP3 and output pin you need. I really wouldn't recommend stealing gates from the output buffer for a Pierce oscillator, as there's far too much risk of crosstalk. A Pierce oscillator spends too much time in the linear region so there would almost certainly be intermodulation due to the supply and ground impedance, leading to Fosc ripple on the top and bottom of the squarewave and if you are unlucky with the gate delays a possible glitch on the rising or falling edge. It would be much safer to use a separate TCXO module which would also improve the uncalibrated frequency accuracy.
And yes, using the ADC input for mode selection is fairly trivial - After adding ADC setup code to the initialisation section, in the main loop simply rip out the line that that sets mode from the GPIO port:
mode=(GPIObits.GP3<<2)|(GPIO&0b11);
replacing it with code that triggers the ADC and waits for the result, then shifts the whole result left one bit adds 0x0080 to it for rounding, then throws away the low byte to get a three bit result in the high byte to stuff into mode directly compatible with the rest of the existing code. (or you could even shift it two bits to keep a 4 bit result and add the intermediate 500KHz, 50KHz, 5KHz, 500Hz, 50Hz and 5Hz frequencies). The minimum hardware is a 1P7T rotary switch (possibly 1P8T if we want to get cute with using it for power as well) and seven equal resistors in a potential divider chain between Vdd and Vss.
On the subject of UIs, 6 LEDs arranged on the sides of a 3x3 grid can be charliplexed with only 3 I/O pins to indicate any one of nine states (without getting into blinking etc.) and the control could be a simple pushbutton to cycle through them or two, one for each side. You'd need a PIC16 to have enough pins but it could be a lot cheaper than a decent quality rotary switch. You can do 12 LEDs with 4 I/O pins which would allow an individual LED for each mode.