Built-in Analog to Digital Converter
Thanks to Gmoon (what's your real name?) for hacking out some code for reading the internal ADC supplied on Hummer units. Visit his Hummer website here.
A little background information. First off, when the designers were making the Hummer they found that the built-in analog-digital converters which are built into the DTV chip were not reliable enough. So they added a 3rd party chip to the design. It is a clone of the SNAD01C. It is an 8-bit serial ADC and it actually has 8 input lines. However, only one of those lines is present on the hummer's PCB. The rest are covered under the epoxy, and like the DTV chip itself, are unreachable.
The chip is attached to the DTV via userport lines 0, 1, and 2. I actually severed these lines on most of my hacked hummer units so that I could have the entire user-port available. Gmoon has provided source code and a compiled program. I have graciously copied them from his website and placed them here:
ADCV11.ASM - Source code, well documented
ADCV11.PRG - Compiled ML program.
adcv11b.asm - Modified version (by me) so that it displays the number on the screen from ML.
adcv11.prg - Just type SYS 49152 to start this version.
Minimal BASIC example:
- Load the code: LOAD"ADCVxx.PRG",8,1 (where xx is version #)
- Call the routine: SYS41952 or JSR $C000
- Get the ADC value: X = PEEK(251) or LDA $FB, etc.
20 PRINT PEEK(251);
- The ADC channel # is 0.
- The read routine is loaded in free memory at $C000 (49152). Reassemble the source
if that's not good for your app.
- The load addr is the entry point.
- Fetch the ADC value from $FB (251) (zpage free memory)
- Routine is 141 bytes (v1.1)
- Delay loops which were originally part of the prog have been removed, as they
weren't needed. A delay remains after the START signal goes LO, as the timing spec indicates a minimum time.
It's quite possible this can also be removed, as the DTV isn't exactly a speed-demon.
- Assembler used was C64ASM v1.1a, a freeware cross-assembler. First time I've used it, worked fine.
How the routine works
The code follows the protocol outlined in this image:
- Bring up START signal, then drop it
- Start CLOCK cycle, each subsequent bit transfer takes one full cycle (HI & LO.) The original routine
included delay loops to normalize the clock, but they weren't needed.
- Send 'ADC command'-- 100
- Send channel # -- 000
- The DIO line is bit 0 of userport--
since each bit can be shifted (to the right) into the bit 0 position, these 6 bits are stored backwards: '000001'.
Of course, only one bit is actually set, but the routine was written so other cmds could be sent to the ADC, if
- Two empty clock cycles follow, while the ADC is capturing the voltage level and converting to digital
- 8 bits of data are now sent from the ADC
- A 9th bit is supposedly sent, but isn't documented in this drawing (the routine adds another clock
cycle after the data, but doesn't save the "PDS" bit (power-down status?) This extra clock tick is included, but
probably not needed--the next START signal would likely reset the ADC.