カテゴリー
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チャンネル混合信号を送出しフィルター検波ー波形整形ーシリアルパラレル変換するところまでできるようになりました。