カテゴリー
writer

自作ROMライター その6

 パソコンから3バイト単位(アドレス16ビット、データ8ビット)で信号を送ることができるようになりました。クロック43Hz、アドレス+データ24ビット、リセット信号をキーボドから入力した値に応じて送りLEDを点灯しています。最後のビットを送った後に書き込み信号を送ることができればROMに書き込みができるはずです。

アドレス・データとして3バイト単位で送出
アドレス・データとして3バイト送る
アドレス・データとして3バイト送る
#include <iostream>
#include <windows.h>
#include <math.h>
#include <MMSystem.h>

#pragma comment (lib, "winmm.lib")

constexpr auto SAMPLING = 192000;
constexpr auto CHANNEL = 2;
constexpr auto BITSPERSAMPLE = 16;
constexpr auto MAXAMP = 32767;
constexpr auto DIV = 4;
constexpr auto BUFFERING = 10;

void createWave(LPWORD lpData, size_t frequency, size_t sampling, WORD amplitude) {
    double wavelength = (double)sampling / (double)frequency;
    double d = 360.0 / wavelength;
    double pi = 3.14159265359;
    for (int i = 0; i < wavelength; i++) {
        lpData[i] = (WORD)(amplitude * sin(d * i / 180.0 * pi));
    }
}

BOOLEAN isON(unsigned char data, size_t bit, size_t bitLength, size_t value) {
    int oneByte = 8;
    for (int i = 0; i < oneByte; i++) {
        unsigned char mask = 0x80 >> i;
        if (((data & mask) == mask) &&
            (bitLength *((bit-oneByte )+i)) <= (value % (bitLength * bit)) &&
            (value % (bitLength * bit)) < (bitLength * ((bit - oneByte + 1) + i))) {
            return true;
        }
    }
    return false;
}

DWORD soundOut(
    LPWORD *lpWaveData,
    HWAVEOUT hWaveOut,
    unsigned char data,
    size_t bit,
    size_t cFrequency,
    BOOL reset
) {
    LPWORD lpSinWave;
    LPWORD lpWave;
    LPWORD lpWave1;
    LPWORD lpWave2;
    LPWORD lpWave3;
    LPWORD lpWave4;
    size_t i, j, end;
    size_t cWavelength = SAMPLING / cFrequency;
    size_t dataLength = (size_t)CHANNEL * (BITSPERSAMPLE / 8) * cWavelength * bit;
    size_t dWavelength;
    size_t dFrequency;
    WORD amplitude = MAXAMP / DIV;

    lpWave = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave1 = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave2 = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave3 = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave4 = (LPWORD)calloc(sizeof(WORD), dataLength);

    end = dataLength/(BITSPERSAMPLE / 8);

    for (i = 0; i < end; i++) {
        lpWave[i] = 0;
        lpWave1[i] = 0;
        lpWave2[i] = 0;
        lpWave3[i] = 0;
        lpWave4[i] = 0;
    }

    /*  チャンネル1 ********************************/
    lpSinWave = (LPWORD)calloc(sizeof(WORD), cWavelength);
    createWave(lpSinWave, cFrequency, SAMPLING, MAXAMP);
    for (i = 0, j = 0; i < end; i += CHANNEL) {
        lpWave[i] = lpSinWave[j];
        ++j;
        if (j >= cWavelength) { j = 0; }
    }
    free(lpSinWave);

    /*  チャンネル2 ********************************/

    // クロック
    dFrequency = 3200;
    dWavelength = SAMPLING / dFrequency;
    lpSinWave = (LPWORD)calloc(sizeof(WORD), dWavelength);
    createWave(lpSinWave, dFrequency, SAMPLING, amplitude);
    for (i = 1, j = 0; i < end; i += CHANNEL) {
        lpWave1[i] = lpSinWave[j];
        ++j;
        if (j >= dWavelength) { j = 0; }
    }
    for (i = 1, j = 0; i < end; i += CHANNEL, ++j) {
        if (j < cWavelength/2) { lpWave1[i] = 0; }
        if (j >= cWavelength) { j = 0; }
    }
    free(lpSinWave);

    // 制御データ
    dFrequency = 8000;
    dWavelength = SAMPLING / dFrequency;
    lpSinWave = (LPWORD)calloc(sizeof(WORD), dWavelength);
    createWave(lpSinWave, dFrequency, SAMPLING, amplitude);
    for (i = 1, j = 0; i < end; i += CHANNEL) {
        lpWave2[i] = lpSinWave[j];
        ++j;
        if (j >= dWavelength) { j = 0; }
    }
    for (i = 1, j = 0; i < end; i += CHANNEL, ++j) {
        if (j < cWavelength/1.2) { lpWave2[i] = 0; }
        if (j >= cWavelength) { j = 0; }
    }
    free(lpSinWave);

    // シリアルデータ2
    dFrequency = 11300;
    dWavelength = SAMPLING / dFrequency;
    lpSinWave = (LPWORD)calloc(sizeof(WORD), dWavelength);
    createWave(lpSinWave, dFrequency, SAMPLING, amplitude);
    for (i = 1, j = 0; i < end; i += CHANNEL, ++j) {
        lpWave3[i] = lpSinWave[j];
        if (j >= dWavelength) { j = 0; }
    }
    for (i = 1; i < end; i += CHANNEL) {
        if (isON(data, bit, cWavelength * CHANNEL, i)) {
            lpWave3[i] = 0;
        }
    }
    free(lpSinWave);

    // リセット
    if (reset) {
        dFrequency = 17000;
        dWavelength = SAMPLING / dFrequency;
        lpSinWave = (LPWORD)calloc(sizeof(WORD), dWavelength);
        createWave(lpSinWave, dFrequency, SAMPLING, amplitude);
        for (i = 1, j = 0; i < cWavelength; i += CHANNEL, ++j) {
            lpWave4[i] = lpSinWave[j];
            if (j >= dWavelength) { j = 0; }
        }
        free(lpSinWave);
    }

    // チャンネル2に合成
    for (i = 1; i < end; i += CHANNEL) {
        lpWave[i] = lpWave1[i] + lpWave2[i] + lpWave3[i] + lpWave4[i];
    }

    *lpWaveData = lpWave;
    return (DWORD)dataLength;
}

int main() {

    LPWORD lpWave[BUFFERING];
    WAVEHDR whdr[BUFFERING];
    WAVEFORMATEX wfe;
    HWAVEOUT hWaveOut;

    wfe.wFormatTag = WAVE_FORMAT_PCM;
    wfe.nChannels = CHANNEL;
    wfe.wBitsPerSample = BITSPERSAMPLE;
    wfe.nBlockAlign = CHANNEL * BITSPERSAMPLE / 8;
    wfe.nSamplesPerSec = SAMPLING;
    wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * wfe.nBlockAlign;
    waveOutOpen(&hWaveOut, 0, &wfe, 0, 0, CALLBACK_NULL);

    for (int i = 0; i < BUFFERING; i++) {
        whdr[i].dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
        whdr[i].dwLoops = 1;
        lpWave[i] = NULL;
    }

    std::string str;
    do {
        std::cout << "2桁毎の16進コードを入力しEnterを押して下さい。(00 ~ FF)" << std::endl;
        std::cout << "続けて入力する場合は間を空けないでください。" << std::endl;
        std::cout << "Ctrl+Zを入力しEnterで終了します。" << std::endl;
        std::cin >> str;

        // Ctrl+Zで終了
        if (std::cin.eof()) { break; }

        char strData[3];
        strData[2] = 0x00;
        size_t bit = 9;
        size_t frequency = 43;
        int freeBuffer = 0;
        for (int i = 0, j = 0, k = 0; i < str.size(); i += 2, j++, k++) {

            if (j >= BUFFERING) {
                j = 0;
            }

            freeBuffer = j + 1;
            if (freeBuffer >= BUFFERING) {
                freeBuffer = 0;
            }
            if (lpWave[freeBuffer] != NULL) {
                std::cout << "free=" << std::dec << freeBuffer << std::endl;
                free(lpWave[freeBuffer]);
                lpWave[freeBuffer] = NULL;
            }

            strData[0] = str[i];
            strData[1] = str[(size_t)i + 1];
            // 入力された文字列をデータに変換
            unsigned char data = (unsigned char)strtol(strData, NULL, 16);

            // サウンド出力
            if (i % 3 == 0) {
                whdr[j].dwBufferLength = soundOut(&lpWave[j], hWaveOut, data, bit, frequency, true);
            }
            else {
                whdr[j].dwBufferLength = soundOut(&lpWave[j], hWaveOut, data, bit-1, frequency, false);
            }
            whdr[j].lpData = (LPSTR)lpWave[j];
            waveOutPrepareHeader(hWaveOut, &whdr[j], sizeof(WAVEHDR));
            waveOutWrite(hWaveOut, &whdr[j], sizeof(WAVEHDR));

            std::cout << "no=" << std::dec << j << ", data=" << std::hex << (int)data << "H" << std::endl;

            if (k > BUFFERING-3) {
                Sleep((1000 * (DWORD)bit) / (DWORD)frequency);
            }
        }
        int num = (int)str.size() / 2;
        if (num == 0) {
            num = 1;
        }
        else if (num > BUFFERING) {
            num = BUFFERING;
        }
        Sleep((1000 * (DWORD)bit * (num +1)) / (DWORD)frequency);
        for (int i = 0; i < num; i++) {
            if (lpWave[i] != NULL) {
                std::cout << "free=" << std::dec << i << std::endl;
                free(lpWave[i]);
                lpWave[i] = NULL;
            }
        }
    } while (true);

    waveOutClose(hWaveOut);
}
カテゴリー
writer

自作ROMライター その5

 ソフトウェアを改良し複数バイトのデータを送り込めるようにしました。これでROMに書き込みたいデータとクロックや制御信号を混合してパソコンからサウンド出力し、受け側の装置で分離してロジックICを意図通りに動かすことができるようになりました。

複数バイトのデータを連続して74LS273に送る
複数バイトのデータを連続して74LS273に送る
#include <iostream>
#include <windows.h>
#include <math.h>
#include <MMSystem.h>

#pragma comment (lib, "winmm.lib")

constexpr auto SAMPLING = 192000;
constexpr auto CHANNEL = 2;
constexpr auto BITSPERSAMPLE = 16;
constexpr auto MAXAMP = 32767;
constexpr auto DIV = 4;
constexpr auto BUFFERING = 10;

void createWave(LPWORD lpData, size_t frequency, size_t sampling, WORD amplitude) {
    double wavelength = (double)sampling / (double)frequency;
    double d = 360.0 / wavelength;
    double pi = 3.14159265359;
    for (int i = 0; i < wavelength; i++) {
        lpData[i] = (WORD)(amplitude * sin(d * i / 180.0 * pi));
    }
}

BOOLEAN isON(unsigned char data, size_t bit, size_t bitLength, size_t value) {
    int oneByte = 8;
    for (int i = 0; i < oneByte; i++) {
        unsigned char mask = 0x80 >> i;
        if (((data & mask) == mask) &&
            (bitLength *((bit-oneByte )+i)) <= (value % (bitLength * bit)) &&
            (value % (bitLength * bit)) < (bitLength * ((bit - oneByte + 1) + i))) {
            return true;
        }
    }
    return false;
}

DWORD soundOut(LPWORD *lpWaveData, HWAVEOUT hWaveOut, unsigned char data, size_t bit, size_t cFrequency) {
    LPWORD lpSinWave;
    LPWORD lpWave;
    LPWORD lpWave1;
    LPWORD lpWave2;
    LPWORD lpWave3;
    LPWORD lpWave4;
    size_t i, j, end;
    size_t cWavelength = SAMPLING / cFrequency;
    size_t dataLength = (size_t)CHANNEL * (BITSPERSAMPLE / 8) * cWavelength * bit;
    size_t dWavelength;
    size_t dFrequency;
    WORD amplitude = MAXAMP / DIV;

    lpWave = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave1 = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave2 = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave3 = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave4 = (LPWORD)calloc(sizeof(WORD), dataLength);

    end = dataLength/(BITSPERSAMPLE / 8);

    for (i = 0; i < end; i++) {
        lpWave[i] = 0;
        lpWave1[i] = 0;
        lpWave2[i] = 0;
        lpWave3[i] = 0;
        lpWave4[i] = 0;
    }

    /*  チャンネル1 ********************************/
    lpSinWave = (LPWORD)calloc(sizeof(WORD), cWavelength);
    createWave(lpSinWave, cFrequency, SAMPLING, MAXAMP);
    for (i = 0, j = 0; i < end; i += CHANNEL) {
        lpWave[i] = lpSinWave[j];
        ++j;
        if (j >= cWavelength) { j = 0; }
    }
    free(lpSinWave);

    /*  チャンネル2 ********************************/

    // クロック
    dFrequency = 3200;
    dWavelength = SAMPLING / dFrequency;
    lpSinWave = (LPWORD)calloc(sizeof(WORD), dWavelength);
    createWave(lpSinWave, dFrequency, SAMPLING, amplitude);
    for (i = 1, j = 0; i < end; i += CHANNEL) {
        lpWave1[i] = lpSinWave[j];
        ++j;
        if (j >= dWavelength) { j = 0; }
    }
    for (i = 1, j = 0; i < end; i += CHANNEL, ++j) {
        if (j < cWavelength/2) { lpWave1[i] = 0; }
        if (j >= cWavelength) { j = 0; }
    }
    free(lpSinWave);

    // 制御データ
    dFrequency = 8000;
    dWavelength = SAMPLING / dFrequency;
    lpSinWave = (LPWORD)calloc(sizeof(WORD), dWavelength);
    createWave(lpSinWave, dFrequency, SAMPLING, amplitude);
    for (i = 1, j = 0; i < end; i += CHANNEL) {
        lpWave2[i] = lpSinWave[j];
        ++j;
        if (j >= dWavelength) { j = 0; }
    }
    for (i = 1, j = 0; i < end; i += CHANNEL, ++j) {
        if (j < cWavelength/1.2) { lpWave2[i] = 0; }
        if (j >= cWavelength) { j = 0; }
    }
    free(lpSinWave);

    // シリアルデータ2
    dFrequency = 11300;
    dWavelength = SAMPLING / dFrequency;
    lpSinWave = (LPWORD)calloc(sizeof(WORD), dWavelength);
    createWave(lpSinWave, dFrequency, SAMPLING, amplitude);
    for (i = 1, j = 0; i < end; i += CHANNEL, ++j) {
        lpWave3[i] = lpSinWave[j];
        if (j >= dWavelength) { j = 0; }
    }
    for (i = 1; i < end; i += CHANNEL) {
        if (isON(data, bit, cWavelength * CHANNEL, i)) {
            lpWave3[i] = 0;
        }
    }
    free(lpSinWave);

    // リセット
    dFrequency = 17000;
    dWavelength = SAMPLING / dFrequency;
    lpSinWave = (LPWORD)calloc(sizeof(WORD), dWavelength);
    createWave(lpSinWave, dFrequency, SAMPLING, amplitude);
    for (i = 1, j = 0; i < cWavelength; i += CHANNEL, ++j) {
        lpWave4[i] = lpSinWave[j];
        if (j >= dWavelength) { j = 0; }
    }
    free(lpSinWave);

    // チャンネル2に合成
    for (i = 1; i < end; i += CHANNEL) {
        lpWave[i] = lpWave1[i] + lpWave2[i] + lpWave3[i] + lpWave4[i];
    }

    *lpWaveData = lpWave;
    return (DWORD)dataLength;
}

int main() {

    LPWORD lpWave[BUFFERING];
    WAVEHDR whdr[BUFFERING];
    WAVEFORMATEX wfe;
    HWAVEOUT hWaveOut;

    wfe.wFormatTag = WAVE_FORMAT_PCM;
    wfe.nChannels = CHANNEL;
    wfe.wBitsPerSample = BITSPERSAMPLE;
    wfe.nBlockAlign = CHANNEL * BITSPERSAMPLE / 8;
    wfe.nSamplesPerSec = SAMPLING;
    wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * wfe.nBlockAlign;
    waveOutOpen(&hWaveOut, 0, &wfe, 0, 0, CALLBACK_NULL);

    for (int i = 0; i < BUFFERING; i++) {
        whdr[i].dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
        whdr[i].dwLoops = 1;
        lpWave[i] = NULL;
    }

    std::string str;
    do {
        std::cout << "2桁毎の16進コードを入力しEnterを押して下さい。(00 ~ FF)" << std::endl;
        std::cout << "続けて入力する場合は間を空けないでください。" << std::endl;
        std::cout << "Ctrl+Zを入力しEnterで終了します。" << std::endl;
        std::cin >> str;

        // Ctrl+Zで終了
        if (std::cin.eof()) { break; }

        char strData[3];
        strData[2] = 0x00;
        size_t bit = 9;
        size_t frequency = 43;
        int freeBuffer = 0;
        for (int i = 0, j = 0, k = 0; i < str.size(); i += 2, j++, k++) {

            if (j >= BUFFERING) {
                j = 0;
            }

            freeBuffer = j + 1;
            if (freeBuffer >= BUFFERING) {
                freeBuffer = 0;
            }
            if (lpWave[freeBuffer] != NULL) {
                std::cout << "free=" << std::dec << freeBuffer << std::endl;
                free(lpWave[freeBuffer]);
                lpWave[freeBuffer] = NULL;
            }

            strData[0] = str[i];
            strData[1] = str[(size_t)i + 1];
            // 入力された文字列をデータに変換
            unsigned char data = (unsigned char)strtol(strData, NULL, 16);

            // サウンド出力
            whdr[j].dwBufferLength = soundOut(&lpWave[j], hWaveOut, data, bit, frequency);
            whdr[j].lpData = (LPSTR)lpWave[j];
            waveOutPrepareHeader(hWaveOut, &whdr[j], sizeof(WAVEHDR));
            waveOutWrite(hWaveOut, &whdr[j], sizeof(WAVEHDR));

            std::cout << "no=" << std::dec << j << ", data=" << std::hex << (int)data << "H" << std::endl;

            if (k > BUFFERING-3) {
                Sleep((1000 * (DWORD)bit) / (DWORD)frequency);
            }
        }
        int num = (int)str.size() / 2;
        if (num == 0) {
            num = 1;
        }
        else if (num > BUFFERING) {
            num = BUFFERING;
        }
        Sleep((1000 * (DWORD)bit * (num +1)) / (DWORD)frequency);
        for (int i = 0; i < num; i++) {
            if (lpWave[i] != NULL) {
                std::cout << "free=" << std::dec << i << std::endl;
                free(lpWave[i]);
                lpWave[i] = NULL;
            }
        }
    } while (true);

    waveOutClose(hWaveOut);
}
カテゴリー
writer

自作ROMライター その4

 74HC164Nでシリアルパラレル変換した後74LS273PCでその値を保持できるか実験してみました。同時にソフトウェアを改良しキーボードからバイト単位に信号を送出できるようにしました。

 キーボードで16進数を1バイト分入力しEnterを押すとその値に応じてLEDが点灯しています。

フリップフロップICにバイト単位データを送る
フリップフロップICにバイト単位データを送る
フリップフロップICにバイト単位データを送る
フリップフロップICにバイト単位データを送る
#include <iostream>
#include <windows.h>
#include <math.h>
#include <MMSystem.h>

#pragma comment (lib, "winmm.lib")

constexpr auto SAMPLING = 192000;
constexpr auto CHANNEL = 2;
constexpr auto BITSPERSAMPLE = 16;

void createWave(LPWORD lpData, size_t frequency, size_t sampling, WORD amplitude) {
    size_t wavelength = SAMPLING / frequency;
    double d = 360.0 / wavelength;
    double pi = 3.14159265359;
    for (int i = 0; i < wavelength; i++) {
        lpData[i] = (WORD)(amplitude * sin(d * (i % wavelength) / 180.0 * pi));
    }
}

BOOLEAN isON(unsigned char data, size_t bit, size_t i) {
    size_t bit9 = bit * 9;
    size_t bit8 = bit * 8;
    size_t bit7 = bit * 7;
    size_t bit6 = bit * 6;
    size_t bit5 = bit * 5;
    size_t bit4 = bit * 4;
    size_t bit3 = bit * 3;
    size_t bit2 = bit * 2;

    if (((data & 0x80) == 0x80) && 0 <= (i % (bit9)) && (i % (bit9)) < (bit)) {
        return true;
    }
    if (((data & 0x40) == 0x40) && (bit) <= (i % (bit9)) && (i % (bit9)) < (bit2)) {
        return true;
    }
    if (((data & 0x20) == 0x20) && (bit2) <= (i % (bit9)) && (i % (bit9)) < (bit3)) {
        return true;
    }
    if (((data & 0x10) == 0x10) && (bit3) <= (i % (bit9)) && (i % (bit9)) < (bit4)) {
        return true;
    }
    if (((data & 0x08) == 0x08) && (bit4) <= (i % (bit9)) && (i % (bit9)) < (bit5)) {
        return true;
    }
    if (((data & 0x04) == 0x04) && (bit5) <= (i % (bit9)) && (i % (bit9)) < (bit6)) {
        return true;
    }
    if (((data & 0x02) == 0x02) && (bit6) <= (i % (bit9)) && (i % (bit9)) < (bit7)) {
        return true;
    }
    if (((data & 0x01) == 0x01) && (bit7) <= (i % (bit9)) && (i % (bit9)) < (bit8)) {
        return true;
    }
    return false;
}

static LPWORD lpWave;
static WAVEHDR whdr;

void soundOut(HWAVEOUT hWaveOut, unsigned char data) {
    LPWORD lpData;
    LPWORD lpWave1;
    LPWORD lpWave2;
    LPWORD lpWave3;
    LPWORD lpWave4;

    // 最初と最後の1sは出力しないので3以上とする
    DWORD terms = 3;

    size_t i, j, k, start, end;
    size_t frequency = 9;
    size_t wavelength = SAMPLING / frequency;
    size_t dataLength = (size_t)CHANNEL * (size_t)SAMPLING * terms;

    lpWave = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave1 = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave2 = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave3 = (LPWORD)calloc(sizeof(WORD), dataLength);
    lpWave4 = (LPWORD)calloc(sizeof(WORD), dataLength);

    end = SAMPLING * CHANNEL;
    WORD amplitude = 32767 / 4;
    for (i = 0; i < end; i++) {
        lpWave[i] = 0;
        lpWave1[i] = 0;
        lpWave2[i] = 0;
        lpWave3[i] = 0;
        lpWave4[i] = 0;
    }

    size_t bit = CHANNEL * SAMPLING / frequency;

    // 最初の1sは出力しない
    start = SAMPLING * CHANNEL;
    end = (size_t)CHANNEL * (size_t)SAMPLING * (size_t)terms;
    // 最後の1sは出力しない
    end -= SAMPLING * CHANNEL;

    size_t valWavelength;
    size_t valFrequency;

    /*  チャンネル1 ********************************/
    lpData = (LPWORD)calloc(sizeof(WORD), wavelength);
    createWave(lpData, frequency, SAMPLING, amplitude);
    for (i = start, j = 0; i < end; i += 2) {
        lpWave[i] = lpData[j];
        ++j;
        if (j >= wavelength) { j = 0; }
    }
    free(lpData);

    /*  チャンネル2 ********************************/

    // クロック
    valFrequency = 3200;
    valWavelength = SAMPLING / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, SAMPLING, amplitude);
    for (i = start + 1, j = 0, k = 0; i < end; i += 2, ++j, ++k) {
        if (k < SAMPLING / frequency / 2) { lpWave1[i] = lpData[j]; }
        if (j >= valWavelength) { j = 0; }
        if (k >= SAMPLING / frequency) { k = 0; }
    }
    free(lpData);

    // シリアルデータ1
    valFrequency = 8000;
    valWavelength = SAMPLING / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, SAMPLING, amplitude);
    for (i = 1, j = 0; i < end; i += 2, ++j) {
        lpWave2[start + i] = lpData[j];
        if (j >= valWavelength) { j = 0; }
    }
    free(lpData);

    // シリアルデータ2
    valFrequency = 11300;
    valWavelength = SAMPLING / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, SAMPLING, amplitude);
    for (i = 1, j = 0; i < end; i += 2, ++j) {
        lpWave3[start + i] = lpData[j];
        if (j >= valWavelength) { j = 0; }
    }
    for (i = 1, j = 0; i < end; i += 2, j += 2) {
        if (j >= bit * 9) { j = 0; }
        if (isON(data, bit, i)) {
            lpWave3[start + i] = 0;
        }
    }
    free(lpData);

    // リセット
    valFrequency = 17000;
    valWavelength = SAMPLING / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, SAMPLING, amplitude);
    for (i = 1; i < end; i += 2, ++j) {
        lpWave4[start + i] = 0;
    }
    for (i = 1, j = 0; i < (end - bit * 9); i += 2, ++j) {
        if ((i % (bit * 9)) < bit) {
            lpWave4[start + i - bit] = lpData[j];
        }
        if (j >= valWavelength) { j = 0; }
    }
    free(lpData);

    // チャンネル2に合成
    for (i = 1; i < end; i += 2) {
        lpWave[i] = lpWave1[i] + lpWave2[i] + lpWave3[i] + lpWave4[i];
    }

    // サウンド出力
    whdr.lpData = (LPSTR)lpWave;
    whdr.dwBufferLength = SAMPLING * (CHANNEL * BITSPERSAMPLE / 8) * terms;
    whdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
    whdr.dwLoops = 1;
    waveOutPrepareHeader(hWaveOut, &whdr, sizeof(WAVEHDR));
    waveOutWrite(hWaveOut, &whdr, sizeof(WAVEHDR));
}
int main() {

    WAVEFORMATEX wfe;
    HWAVEOUT hWaveOut;

    wfe.wFormatTag = WAVE_FORMAT_PCM;
    wfe.nChannels = CHANNEL;
    wfe.wBitsPerSample = BITSPERSAMPLE;
    wfe.nBlockAlign = CHANNEL * BITSPERSAMPLE / 8;
    wfe.nSamplesPerSec = SAMPLING;
    wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * wfe.nBlockAlign;

    waveOutOpen(&hWaveOut, 0, &wfe, 0, 0, CALLBACK_NULL);

    char str[128];
    do {
        std::cout << "2桁の16進コードを入力しEnterを押して下さい。(00 ~ FF)" << std::endl;
        std::cout << "Ctrl+Zを入力しEnterを入力すると終了します。" << std::endl;
        std::cin >> str;

        // 入力された文字列をデータに変換
        unsigned char data = (unsigned char)strtol(str, NULL, 16);

        // Ctrl+Zで終了
        if (std::cin.eof()) { break; }

        // データをサウンド出力する
        soundOut(hWaveOut, data);
    } while (true);

    waveOutClose(hWaveOut);
}

 ここまででPCのサウンド出力を使ってデジタル素子を制御出来ることが解りました。

カテゴリー
writer

自作ROMライター その3

 74HC164Nでシリアルパラレル変換ができるとはByteデータを送り込めるということになります。ソフトウェアを改良しByte単位にデータを送れるか実験してみました。

バイトデータを送出
バイトデータを送出
15バイト分の波形

 ピークが15回出ています。これが74HC164Nにリセット信号を送っているところで、その手前が1バイトのビットデータとなります。74HC164NはNOT出力ですので信号が立っているところが0、立っていないところが1と解釈してください。1、3、5、7と増えていくのが波形からわかります。

1バイト分を拡大した様子
1バイト分を拡大した様子
1ビット分を拡大した様子
1ビット分を拡大した様子
さらに拡大し信号が混合している様子
さらに拡大し信号が混合している様子
#include <iostream>
#include <windows.h>
#include <math.h>
#include <MMSystem.h>

#pragma comment (lib, "winmm.lib")

void createWave(LPWORD lpData, size_t frequency, size_t sampling, WORD amplitude) {
    size_t wavelength = sampling / frequency;
    double d = 360.0 / wavelength;
    double pi = 3.14159265359;
    for (int i = 0; i < wavelength; i++) {
        lpData[i] = (WORD)(amplitude * sin(d * (i % wavelength) / 180.0 * pi));
    }
}

BOOLEAN isON(unsigned char data, size_t bit, size_t i) {
    size_t bit9 = bit * 9;
    size_t bit8 = bit * 8;
    size_t bit7 = bit * 7;
    size_t bit6 = bit * 6;
    size_t bit5 = bit * 5;
    size_t bit4 = bit * 4;
    size_t bit3 = bit * 3;
    size_t bit2 = bit * 2;

    if (((data & 0x80) == 0x80) && 0 <= (i % (bit9)) && (i % (bit9)) < (bit)) {
        return true;
    }
    if (((data & 0x40) == 0x40) && (bit) <= (i % (bit9)) && (i % (bit9)) < (bit2)) {
        return true;
    }
    if (((data & 0x20) == 0x20) && (bit2) <= (i % (bit9)) && (i % (bit9)) < (bit3)) {
        return true;
    }
    if (((data & 0x10) == 0x10) && (bit3) <= (i % (bit9)) && (i % (bit9)) < (bit4)) {
        return true;
    }
    if (((data & 0x08) == 0x08) && (bit4) <= (i % (bit9)) && (i % (bit9)) < (bit5)) {
        return true;
    }
    if (((data & 0x04) == 0x04) && (bit5) <= (i % (bit9)) && (i % (bit9)) < (bit6)) {
        return true;
    }
    if (((data & 0x02) == 0x02) && (bit6) <= (i % (bit9)) && (i % (bit9)) < (bit7)) {
        return true;
    }
    if (((data & 0x01) == 0x01) && (bit7) <= (i % (bit9)) && (i % (bit9)) < (bit8)) {
        return true;
    }
    return false;
}

int main() {

    WAVEFORMATEX wfe;
    static HWAVEOUT hWaveOut;
    static WAVEHDR whdr;
    static LPWORD lpWave;
    static LPWORD lpWave1;
    static LPWORD lpWave2;
    static LPWORD lpWave3;
    static LPWORD lpWave4;
    static LPWORD lpData;

    // 最初と最後の1sは出力しないので3以上とする
    DWORD terms = 17;

    size_t i, j, k, start, end;
    size_t frequency = 9;
    size_t sampling = 192000;
    size_t wavelength = sampling / frequency;

    wavelength = sampling / frequency;
    wfe.wFormatTag = WAVE_FORMAT_PCM;
    wfe.nChannels = 2;
    wfe.wBitsPerSample = 16;
    wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 8;
    wfe.nSamplesPerSec = (DWORD)sampling;
    wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * wfe.nBlockAlign;
    waveOutOpen(&hWaveOut, 0, &wfe, 0, 0, CALLBACK_NULL);
    lpWave = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms);
    lpWave1 = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms);
    lpWave2 = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms);
    lpWave3 = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms);
    lpWave4 = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms);

    end = sampling * wfe.nChannels;
    WORD amplitude = 32767/4;
    for (i = 0; i < end; i++) {
        lpWave[i] = 0;
        lpWave1[i] = 0;
        lpWave2[i] = 0;
        lpWave3[i] = 0;
        lpWave4[i] = 0;
    }

    // 最初の1sは出力しない
    start = sampling * wfe.nChannels;
    end = wfe.nChannels * sampling * terms;
    // 最後の1sは出力しない
    end -= sampling * wfe.nChannels;

    size_t valWavelength;
    size_t valFrequency;

    size_t bit = wfe.nChannels * sampling / frequency;

    /*  チャンネル1 ********************************/
    lpData = (LPWORD)calloc(sizeof(WORD), wavelength);
    createWave(lpData, frequency, sampling, amplitude);
    for (i = start, j = 0; i < end; i += 2) {
        lpWave[i] = lpData[j];
        ++j;
        if (j >= wavelength) { j = 0; }
    }
    free(lpData);

    /*  チャンネル2 ********************************/

    // クロック
    valFrequency = 3200;
    valWavelength = sampling / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, sampling, amplitude);
    for (i = start + 1, j = 0, k = 0; i < end; i += 2, ++j, ++k) {
        if (k < sampling / frequency / 2) { lpWave1[i] = lpData[j]; }
        if (j >= valWavelength) { j = 0; }
        if (k >= sampling / frequency) { k = 0; }
    }
    free(lpData);

    const unsigned char dataList[] = {
    0x01,
    0x03,
    0x07,
    0x0F,
    0x1F,
    0x3F,
    0x7F,
    0xFF,
    0x7F,
    0x3F,
    0x1F,
    0x0F,
    0x07,
    0x03,
    0x01
    };
    size_t dataLen = sizeof(dataList) / sizeof(*dataList);
    unsigned char data = 0x00;

    // シリアルデータ1
    valFrequency = 8000;
    valWavelength = sampling / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, sampling, amplitude);
    for (i = 1, j = 0; i < end; i += 2, ++j) {
        lpWave2[start + i] = lpData[j];
        if (j >= valWavelength) { j = 0; }
    }
    free(lpData);

    // シリアルデータ2
    valFrequency = 11300;
    valWavelength = sampling / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, sampling, amplitude);
    for (i = 1, j = 0; i < end; i += 2, ++j) {
        lpWave3[start + i] = lpData[j];
        if (j >= valWavelength) { j = 0; }
    }
    for (i = 1, j = 0, k = 0; i < end; i += 2, j += 2) {
        data = dataList[k];
        if (j >= bit * 9) { j = 0; ++k; }
        if (k >= dataLen) { k = 0; }
        if (isON(data, bit, i)) {
            lpWave3[start + i] = 0;
        }
    }
    free(lpData);

    // リセット
    valFrequency = 17000;
    valWavelength = sampling / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, sampling, amplitude);
    for (i = 1; i < end; i += 2, ++j) {
        lpWave4[start + i] = 0;
    }
    for (i = 1, j = 0; i < end; i += 2, ++j) {
        if ((i % (bit * 9)) < bit) {
            lpWave4[start + i - bit] = lpData[j];
        }
        if (j >= valWavelength) { j = 0; }
    }
    free(lpData);

    // チャンネル2に合成
    for (i = 1; i < end; i += 2) {
        lpWave[i] = lpWave1[i] + lpWave2[i] + lpWave3[i] + lpWave4[i];
    }

    // サウンド出力
    whdr.lpData = (LPSTR)lpWave;
    whdr.dwBufferLength = wfe.nAvgBytesPerSec * terms;
    whdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
    whdr.dwLoops = 1;
    waveOutPrepareHeader(hWaveOut, &whdr, sizeof(WAVEHDR));
    waveOutWrite(hWaveOut, &whdr, sizeof(WAVEHDR));

    char str[128];
    std::cout << "hello, world\n";
    std::cin >> str;

}
カテゴリー
writer

自作ROMライター その2

 アナログ信号をデジタル信号のようにON/OFFしてLEDを明滅させたとしても信号自体はアナログであるためそのままでデジタル素子を制御できるわけではありません。

 そこでデジタル素子で扱える信号にするため74HC14APを使いhigh:+5V, low:0Vの本物のデジタル信号にできるか実験してみました。

ROMライターデジタルへ変換
ROMライターデジタルへ変換

 4chフィルタから出た信号を検波(復調)後74HC14APで波形を整え74HC164Nでシリアルパラレル変換しました。

#include <iostream>
#include <windows.h>
#include <math.h>
#include <MMSystem.h>

#pragma comment (lib, "winmm.lib")

void createWave(LPWORD lpData, size_t frequency, size_t sampling, WORD amplitude) {
    size_t wavelength = sampling / frequency;
    double d = 360.0 / wavelength;
    double pi = 3.14159265359;
    for (int i = 0; i < wavelength; i++) {
        lpData[i] = (WORD)(amplitude * sin(d * (i % wavelength) / 180.0 * pi));
    }
}

int main() {

    WAVEFORMATEX wfe;
    static HWAVEOUT hWaveOut;
    static WAVEHDR whdr;
    static LPWORD lpWave;
    static LPWORD lpWave1;
    static LPWORD lpWave2;
    static LPWORD lpWave3;
    static LPWORD lpWave4;
    static LPWORD lpData;

    // 最初と最後の1sは出力しないので3以上とする
    size_t terms = 402;

    size_t i, j, k, start, end, cycle;
    size_t frequency = 16;
    size_t sampling = 192000;
    size_t wavelength = sampling / frequency;

    wavelength = sampling / frequency;
    wfe.wFormatTag = WAVE_FORMAT_PCM;
    wfe.nChannels = 2;
    wfe.wBitsPerSample = 16;
    wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 8;
    wfe.nSamplesPerSec = (DWORD)sampling;
    wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * wfe.nBlockAlign;
    waveOutOpen(&hWaveOut, 0, &wfe, 0, 0, CALLBACK_NULL);
    lpWave = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms);
    lpWave1 = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms);
    lpWave2 = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms);
    lpWave3 = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms);
    lpWave4 = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms);

    end = sampling * wfe.nChannels * 1;
    WORD amplitude = 32767/4;
    for (i = 0; i < end; i++) {
        lpWave[i] = 0;
        lpWave1[i] = 0;
        lpWave2[i] = 0;
        lpWave3[i] = 0;
        lpWave4[i] = 0;
    }

    // 最初の1sは出力しない
    start = sampling * wfe.nChannels * 1;
    end = wfe.nChannels * sampling * terms;
    // 最後の1sは出力しない
    end -= sampling * wfe.nChannels * 1;

    size_t valWavelength;
    size_t valFrequency;

    cycle = frequency;

    /*  チャンネル1 ********************************/
    lpData = (LPWORD)calloc(sizeof(WORD), wavelength);
    createWave(lpData, frequency, sampling, amplitude);
    for (i = start, j = 0; i < end; i += 2) {
        lpWave[i] = lpData[j];
        ++j;
        if (j >= wavelength) { j = 0; }
    }
    free(lpData);

    /*  チャンネル2 ********************************/

    // クロック
    valFrequency = 3200;
    valWavelength = sampling / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, sampling, amplitude);
    for (i = start + 1, j = 0, k = 0; i < end; i += 2, ++j, ++k) {
        if (k < sampling / cycle / 2) { lpWave1[i] = lpData[j]; }
        if (j >= valWavelength) { j = 0; }
        if (k >= sampling / cycle) { k = 0; }
    }
    free(lpData);

    // シリアルデータ1
    valFrequency = 8000;
    valWavelength = sampling / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, sampling, amplitude);
    for (i = 0, j = 0; i < end; i += 2, ++j) {
        lpWave2[1 + i] = lpData[j];
        if (j >= valWavelength) { j = 0; }
    }
    free(lpData);
    for (i = 0,j = 0, k = 0; i < end- (wfe.nChannels * sampling / cycle * 2); i += 2, ++k) {
        if (j < 8) {
            lpWave2[start + 1 + i + (wfe.nChannels * sampling / cycle * 2)] = 0;
        }
        if (k >= sampling / cycle) {
            k = 0;
            ++j;
        }
        if (j >= 8) { j = 0; }
    }

    // シリアルデータ2
    valFrequency = 11300;
    valWavelength = sampling / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, sampling, amplitude);
    for (i = 0, j = 0; i < end; i += 2, ++j) {
        lpWave3[1 + i] = lpData[j];
        if (j >= valWavelength) { j = 0; }
    }
    free(lpData);
    for (i = 0, j = 0, k = 0; i < end - (wfe.nChannels * sampling / cycle * 2); i += 2, ++k) {
        if (j < 3) {
            lpWave3[start + 1 + i + (wfe.nChannels * sampling / cycle * 2)] = 0;
        }
        if (k >= sampling / cycle) {
            k = 0;
            ++j;
        }
        if (j >= 8) { j = 0; }
    }

    // リセット
    valFrequency = 17000;
    valWavelength = sampling / valFrequency;
    lpData = (LPWORD)calloc(sizeof(WORD), valWavelength);
    createWave(lpData, valFrequency, sampling, amplitude);
    for (i = 0, j = 0; i < end; i += 2, ++j) {
        lpWave4[start + 1 + i] = lpData[j];
        if (j >= valWavelength) { j = 0; }
    }
    free(lpData);
    for (i = 0; i < end; i += 2) {
        if (wfe.nChannels * sampling / cycle * 1 < i) {
            lpWave4[start + 1 + i] = 0;
        }
    }

    // チャンネル2に合成
    for (i = 1, j = 0; i < end; i += 2) {
        lpWave[i] = lpWave1[i] + lpWave2[i] + lpWave3[i] + lpWave4[i];
    }

    // サウンド出力
    whdr.lpData = (LPSTR)lpWave;
    whdr.dwBufferLength = wfe.nAvgBytesPerSec * terms;
    whdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
    whdr.dwLoops = 1;
    waveOutPrepareHeader(hWaveOut, &whdr, sizeof(WAVEHDR));
    waveOutWrite(hWaveOut, &whdr, sizeof(WAVEHDR));

    char str[128];
    std::cout << "hello, world\n";
    std::cin >> str;

}
74HC14APの出力
74HC14APの出力
74HC14APの出力
74HC14APの出力

 デジタルのようなアナログ信号が綺麗な矩形波に整えられているいることがわかる波形です。

 ソフトウェアでPCのサウンド出力にクロック、リセット、データの3チャンネル混合信号を送出しフィルター検波ー波形整形ーシリアルパラレル変換するところまでできるようになりました。