74HC164Nでシリアルパラレル変換した後74LS273PCでその値を保持できるか実験してみました。同時にソフトウェアを改良しキーボードからバイト単位に信号を送出できるようにしました。
キーボードで16進数を1バイト分入力しEnterを押すとその値に応じてLEDが点灯しています。
#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のサウンド出力を使ってデジタル素子を制御出来ることが解りました。