Table of Contents

Elcotel reverse engineering

Initially I was struggling trying to program Elcotel 5 controller and attempted to reverse-engineer the configuration files. Now that I can program the phone, it is less of a priority, but I'll still be working on the rate files. Unlike with Protel, you can't easily create one, since the local NPA-s (area codes) cannot be removed once added, and they determine the home area code. You can't start from scratch - need to work on the existing file, which usually is one for Florida supplied with the software.

With a limited time, I have some goals. Ultimate goal is to better understand it and be able to program in alternative ways.

  1. Rate files. To be able to create one myself. Unfortunately the binary structure is very irregular, so far I wasn't able to decode it.
  2. 28C64 rates EEPROM. Most of them are soldered, I removed mine and put a socket so I can easily see the memory map and what's changed. It might be worth sometimes to preserve the original state, vs. just erasing. At first I just wanted to pull the station ID, bypass and password. Its location varies and overall it seems overengineered, just as the Elcotel electronics :-|
  3. Firmware EPROM structure. Initially I wanted to disassemble it, tools are available even online for this popular Z80 CPU. But, surprisingly the output is sort of a nonsense. Perhaps obusfcated in some way? But data & address lines to the CPU are not scrambled. The other goal in my mind and potentially a super easy way to help other people programming their phones, is to replace the standard rates and config which you get upon factory reset. That way we could just send out the program ROM, which sits in the socket.
  4. Modem transmission. Someone already started, there's a youtube video essentially to hack the station ID. Pretty simple, but not so easy with the password. The idea is to create alternative, modern program so you don't need to install windows 95.

Strange story: I ordered a “new” 28C64 chip on ebay, and I got a recycled one. It's hard to get a really new - old stock. Once I read it in my programmer, I thought I was going insane. It wasn't blank and it was… Elcotel 5 rate chip. Station number I extracted appears to be 989-773-7717 (Saginaw, Midland, and Bay City in Michigan).
Strange story 2: Payphone I removed in Phoenix AZ, rate EPROM had a station number from Albuquerque - 505

Rates EEPROM

Some random notes so far:

Voice EPROM

Briefly looking into 128kB voice EPROM, I made some conclusions:

A simple program to decode is listed below. It does work, although the sound quality is not as good as original. Listen to the samples on Elcotel page. Input file must be VOICE_ROM.BIN and it outputs to output.raw. Output format is 8 bit signed PCM, 9690 Hz [estimation based on the digitized dial tone in the EPROM, but 9600 number seems much more familiar - a common modem baud rate].

#include <stdio.h>
#include <assert.h>
#include <inttypes.h>

int main(void) {
    FILE *ifp, *ofp;
    uint8_t src_value;            //byte read
    float DSP_0 = 0;              //current integrator output
    float DSP_1 = 0;              //previous integrator output (needed for averaging two samples, somehow it reduces the noise)
    float n = 0.2151;             //filter coefficient - strength of the new bit
    int8_t out_value;             //output PCM stream value (signed 8-bit) (somehow 16-bit would not improve anything)
    int b=0;                      //bit, converted to +/-1

    ifp = fopen("VOICE_ROM.BIN", "rb");
    ofp = fopen("output.raw", "wb");
    assert(ifp);
    assert(ofp);

    do {
        src_value = fgetc(ifp);
        for (int i=0; i<8; i++) {
            DSP_1=DSP_0;
            b=(src_value&1)?1:(-1);                   //+1 for 1, -1 for 0
            src_value>>=1;
            DSP_0=DSP_0*(1-n)+n*b;
            out_value=round((DSP_0/2+DSP_1/2)*127);   //averaging 2 samples + rescale +/-1 into +/-127 (signed int8)
            if (i&1) fputc(out_value, ofp);           //writing every other bit
         }
    } while (!feof(ifp));
    fclose(ofp);
    fclose(ifp);

    return 0;
}