«Музыка» цифровой шины с интерфейсом UART

«Музыка» цифровой шины с интерфейсом UART

Привет, Geektimes! Вам было когда нибудь интересно, как «звучит» электрический сигнал, проходящий по дорожкам печатных плат между микросхем, транзисторов, диодов, резисторов и конденсаторов? Один из вариантов такого сигнала в современной электронике — цифровая шина, а один из популярных интерфейсов для обмена данных по шине — UART. Он часто используется в микроконтроллерах для связи с компьютером или какой либо переферией. Чтобы получить звук на шине, вовсе не обязательно подключать динамик с усилителем к реальной шине с UARTом, ведь ее можно симулировать в программе. Вам интересно, какие звуки в итоге получились, или нужна программа, чтобы самому поэкспериментировать? Тогда прошу под кат.

Слушаем файлы на шине с UART

Какой звук получится, если передавать файлы через UART? Вот некоторые примеры, полученные при следующих параметрах UART:

  • Скорость 115200 бод
  • Разрядность 8 бит
  • Бит проверки на четность: отсутствует
  • Длина стоп бита: 1

Звук игры Сталкер Тень Чернобыля (файл XR_3DA.exe, в самом конце трека, начиная с 2:36, есть мелодия).

Звук текста и кода статьи про синтезатор речи (сама статья тут).

Как звучит фотография «Лены»?

image

Получился просто шум.

Звук книги «Энтропия и прогноз времянных рядов в теории динамических систем» в pdf формате.

Звук прошивки микроконтроллера серии Atmega для wav плеера.

Для чего это можно использовать?

Теоретически, может быть такая информация в виде текста, или картинки, или видео, или в виде программы, которая будет иметь не только функциональный смысл или эстетическую значимость, но также и «красивый» звук цифровой шины, тогда это получается некая «цифровая» поэзия. Также можно разнообразить сэмплы для дабстепа Вообще, на мой взгляд, слушать звуки цифровой шины примерно так же интересно, как слушать шум радиоволн на коротких волнах, в общем на любителя.

Как это работает или немного про UART

Что такое UART можно почитать на википедии. UART очень легко симулировать в программе. По сути необходимо лишь уметь создавать перепад сигнала от 0 до 1 и обратно (в случае WAV файла с разрядностью 16 бит, это значения от —A до +A, где A это ампилутда сигнала) и записывать его в звуковой файл. Интерфейс UART функционирует примерно так: после стартового бита, который равен логическому «нулю», нужно выставлять уровень в зависимости от предоставленных данных, от младшего бита к старшему. Далее идет бит четности, который можно не использовать. Под конец сообщения ставится стоп бит (логическая «единица»), длина которого может быть разной. Пример кода можно посмотреть в исходниках, которые есть в конце статьи. Подробнее про UART можно посмотреть в сети, материала очень много. UART можно использовать не по назначению, например как ШИМ, а в нашем случае это означает, что теоретически можно даже передать полноценный звуковой сигнал сразу на динамик, как это делается в wav плеерах на микроконтроллере. Однако, я скорее предлагаю использовать его как генератор меандра. Частоту тона и фазу сигнала при этом можно предоставлять в виде бит данных, например 00001111 создаст меандр, период которого будет равен 10-ти периодам времени передачи одного бита (так как в данном случае есть еще стартовый бит, равный 0, и стоповый бит, равный 1). Из-за стартового и стопового бита не все периоды меандров получится передать, например в таком случае 01100110, так как по сути мы будем слушать такую последовательность на шине 0011001101. Если использовать высокую скорость передачи данных, например 115200 бод, то имеет смысл создавать слышимые звуковые частоты, растянув периоды меадров на несколько байт.

По данной ссылке можно скачать программу для преобразования файла в звук шины UART. Также есть версия с использованием OpenAL, чтобы воспроизводить звук в процессе работы программы, вот ссылка.

Исходный код программы предоставлен ниже:

Заголовочный файл SoundsDigitalBus.h

#ifndef SOUNDS_DIGITAL_BUS_H_INCLUDED #define SOUNDS_DIGITAL_BUS_H_INCLUDED  #define SDB_WAV_FILE_NAME "sdb_output.wav" #define SDB_UART_BIT 8 #define SDB_UART_PARITY 0 #define SDB_UART_STOP_BIT 1 #define SDB_UART_BAUDRATE 9600 #define SDB_UART_BAUDRATE_MAX 921600  /// максимальное значение (амплитуда) сэмпла аудио #define SDB_MAX_DATA 30000 /// каналов в аудио #define SDB_CANNEL 1 /// кол-во бит (разрешение) аудио #define SDB_BIT 16 /// частота дискретизации аудио #define SDB_FREQUENCY 96000 /// Количество буферов в очереди OpenAL #define OPENAL_NUM_OF_DYNBUF 32 /// Настройки OpenAL #define SDB_OPENAL_BIT SDB_BIT #define SDB_OPENAL_CANNEL SDB_CANNEL #define SDB_OPENAL_FREQUENCY SDB_FREQUENCY #define SDB_OPENAL_FORMAT AL_FORMAT_MONO16 /// Количество байт в буфере #define SDB_BUFFER_MAX 4800   /// использовать OpenAL для вывода аудио (если Да, то выставить 1) #define SDB_WITH_OPENAL 1 /// режим отладки (если Да, то выставить 1) #define SDB_WITH_DEBUG_MODE 0  #if SDB_WITH_OPENAL == 1 // Подключение библиотеки OpenAL Для вывода звука #include  #include  #endif  #if SDB_WITH_DEBUG_MODE == 1 // Для режима отладки #include  #include  #endif  //для работы с файлами #include  //для работы со строками #include     class sdb { private: #if SDB_WITH_OPENAL == 1     // работа с openAl взята из библиотеки     // синтезатора речи speesy     ALCdevice* openAlDevice;     ALCcontext* openAlContext;     ALuint openAlSource;     signed char openAlnBuf; //количество буферов #endif     // ----------------------------------------     // для записи в WAV файл     FILE *fpSave;     unsigned short wavBlockAlign;     unsigned long wavSubchunk2Size;     unsigned long wavChunkSize;     unsigned char wavLenDataType;     // ----------------------------------------     // для генерирования звуков шин данных     double dTime; // длина времени одного сэмпла, в с.     double allTime; // общее время трека     short busState; // состояние шины (уровень сигнала)     short busDataOne[SDB_BUFFER_MAX]; // буферы, куда пишем wav     short busDataTwo[SDB_BUFFER_MAX];     unsigned char switchBuffer; // переключатель между буферами     unsigned int posBufferOne, posBufferTwo; // позиция в буферах     unsigned int posAllBuffer; // общая позиция     char wavFileName[512]; // имя wav файла     char isCreateWavFileFlag; // флаг, что wav файл был создан     char isBufferOneFlag; // флаг, что готов первый буфер     char isBufferTwoFlag;     unsigned int uartBaudrate; // скорость UART в бод     unsigned int uartT;     unsigned char uartBit; // количество бит     unsigned char uartStopBit; // количество стоп бит     unsigned char uartParityBit;     unsigned char isAudioOutput;     unsigned char isWavFileOutput; #if SDB_WITH_OPENAL == 1     ALboolean CheckALCError(void);     ALboolean CheckALError(void);     char initOpenAL(void);     void destroyOpenAL(void);     void playOpenAlSound(void);     void stopOpenAlSound(void);     void closeOpenAlSound(void);     int getBufferStatusOpenAl(void);     void setBufferOpenAl(signed short *buf,unsigned long siz);     char updateOpenAl(void); #endif     char createWavFile(char * filename,unsigned long sampleRate,unsigned short bitsPerSample, unsigned short numChannels);     void writeSampleWavFile(void *data);     void writeDataBlockWavFile(void *data,unsigned long len);     void closeWavFile(void);     void busDelay(unsigned short us);  public:     sdb(void);     ~sdb(void);     /** @brief функция генерирует звук одного байта шины 1-wire         @param[in] data байт для отправки по 1-wire     */     void oneWireSendByte(unsigned char data);     /** @brief генерирует звук сброса шины 1-wire     */     void oneWireReset(void);      /** @brief останаливает работу шины 1- wire     */     void oneWireStop(void);      /** @brief передает один байт по шине UART         @param[in] data один символ шины UART     */     void uartSendByte(unsigned char data);      /** @brief передает данные по шине UART         @param[in] data один символ шины UART     */     void uartSend(unsigned long data);      /** @brief устанавливает скорость UART         @param[in] baudrate скорость шины UART     */     void uartSetBaudrate(unsigned long baudrate);      /** @brief устанавливает количество отправляемых бит         @param[in] bit количество бит, отправляемых шиной UART за один раз     */     void uartSetBit(unsigned char bit);      /** @brief устанавливает количество стоп битов         Данная функция устаналивает количество стоп битов.         Минимальное значение стоп бита 1.         @param[in] bit количество стоп битов     */     void uartSetStopBit(unsigned char bit);      /** @brief устанавливает бит четности         Данная функция устанавливает флаг использования в UART бита четности.         Если передать 1, то бит четности будет задействован, если передать 0, то         передача данных по UART будет идти без бита четности.         @param[in] state флаг, включающий бит четности.     */     void uartSetParityBit(unsigned char state);      /** @brief функция останавливает передачу UART         Данная функция завершает работу UART, сохраняет или воспроизводит оставшиеся байты.         Функцию вызывать обязательно в конце передачи данных по шине.     */     void uartStop(void);      /** @brief функция устанавливает имя wav файла         @param[in] filename имя wav файла     */     void setWavFileName(char* filename);      /** @brief включить вывод аудио через OpenAL     */     void playAudioOn(void);      /** @brief выключить вывод аудио через OpenAL     */     void playAudioOff(void);      /** @brief включить запись аудио в wav файл     */     void recordOn(void);      /** @brief выключить запись аудио в wav файл     */     void recordOff(void); };   #endif // MUSICDIGITALBUS_H_INCLUDED 

Исходный код файла SoundsDigitalBus.cpp

#include "SoundsDigitalBus.h" #if SDB_WITH_OPENAL == 1     // обработчики ошибок     ALboolean sdb::CheckALCError(void) {         ALenum ErrCode;         ErrCode = alcGetError(openAlDevice);         if (ErrCode != ALC_NO_ERROR) {             return AL_FALSE;         }         return AL_TRUE;     }     ALboolean sdb::CheckALError(void) {         ALenum ErrCode;         if ((ErrCode = alGetError()) != AL_NO_ERROR) {             return AL_FALSE;         }         return AL_TRUE;     }      // инициализация OpenAL     char sdb::initOpenAL(void) {         ALfloat SourcePos[] = {0.0, 0.0, 0.0};         ALfloat SourceVel[] = {0.0, 0.0, 0.0};         // Позиция слушателя.         ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };         // Скорость слушателя.         ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };         // Ориентация слушателя. (Первые 3 элемента – направление «на», последние 3 – «вверх»)         ALfloat ListenerOri[] = { 0.0, 0.0, -1.0,  0.0, 1.0, 0.0 };         #if SDB_WITH_DEBUG_MODE == 1         printf("alcOpenDevicen");         #endif          openAlDevice = alcOpenDevice(0); // open default device         if (openAlDevice != 0) {             openAlContext = alcCreateContext(openAlDevice,0); // create context             if (openAlContext != 0) {                 #if SDB_WITH_DEBUG_MODE == 1                 printf("alcMakeContextCurrentn");                 #endif                 alcMakeContextCurrent(openAlContext); // set active context             } else  {                 #if SDB_WITH_DEBUG_MODE == 1                 printf("Error contextn");                 #endif                 return 0;             }         } else {             #if SDB_WITH_DEBUG_MODE == 1             printf("Error Open Devicen");             #endif             return 0;         }          // Позиция         alListenerfv(AL_POSITION,    ListenerPos);         // Скорость         alListenerfv(AL_VELOCITY,    ListenerVel);         // Ориентация         alListenerfv(AL_ORIENTATION, ListenerOri);          alGenSources(1, &openAlSource);         if (!CheckALError())             return false;          alSourcef (openAlSource, AL_PITCH,    1.0f);         alSourcef (openAlSource, AL_GAIN,    1.0f);         alSourcefv(openAlSource, AL_POSITION,  SourcePos);         alSourcefv(openAlSource, AL_VELOCITY,  SourceVel);         alSourcei (openAlSource, AL_LOOPING,  AL_FALSE);          alSourcei(openAlSource, AL_LOOPING, AL_FALSE);         openAlnBuf = 0;         return 1;     }      void sdb::destroyOpenAL(void) {         alSourceStop(openAlSource);         // Выключаем текущий контекст         alcMakeContextCurrent(0);         // Уничтожаем контекст         alcDestroyContext(openAlContext);         // Закрываем звуковое устройство         alcCloseDevice(openAlDevice);     }      void sdb::playOpenAlSound(void) {         alSourcePlay(openAlSource);     }      void sdb::stopOpenAlSound(void) {         alSourceStop(openAlSource);     }      void sdb::closeOpenAlSound(void) {         alSourceStop(openAlSource);         if (alIsSource(openAlSource))             alDeleteSources(1, &openAlSource);     }      int sdb::getBufferStatusOpenAl(void) {         int processed = 0;         if (openAlnBuf == 0)             return 1;         alGetSourcei(openAlSource, AL_BUFFERS_PROCESSED, &processed);         CheckALError();         #if SDB_WITH_DEBUG_MODE == 1             printf("getBufferStatus: %dn",processed);         #endif         if (processed != 0) {             return processed;         }         return 0;     }      void sdb::setBufferOpenAl(signed short* buf, unsigned long siz) {         int processed = 0;         ALuint BufID = 0;         #if _OPENAL_FORMAT == AL_FORMAT_MONO16         siz = siz*2;         #endif // _OPENAL_FORMAT         #if _OPENAL_FORMAT == AL_FORMAT_STEREO16         siz = siz*4;         #endif // _OPENAL_FORMAT         #if _OPENAL_FORMAT == AL_FORMAT_STEREO8         siz = siz*2;         #endif // _OPENAL_FORMAT         // Получаем количество отработанных буферов         alGetSourcei(openAlSource, AL_BUFFERS_PROCESSED, &processed);         CheckALError();         //если отработанных буферов нет, есть новые данные и число буферов не превысило максимума         if ((processed == 0) && (openAlnBuf < OPENAL_NUM_OF_DYNBUF)) {             openAlnBuf++; //увеличиваем число буферов             alGenBuffers(1, &BufID); //создаем новый буфер             alBufferData(BufID,SDB_OPENAL_FORMAT,buf,siz,SDB_OPENAL_FREQUENCY); //загружаем данные в новый буфер             alSourceQueueBuffers(openAlSource, 1, &BufID); //добавляем буфер в очередь             if (openAlnBuf == 1)                 alSourcePlay(openAlSource);         } else {             #if SDB_WITH_DEBUG_MODE == 1                 printf("processed: %d openAlnBuf: %dn",processed,openAlnBuf);             #endif             // ждем, когда будет обработан хотя бы один буфер             while (getBufferStatusOpenAl() == 0);             // убираем из очереди буфер             alSourceUnqueueBuffers(openAlSource, 1, &BufID);             CheckALError();             // загружаем новый буфер             alBufferData(BufID,SDB_OPENAL_FORMAT,buf,siz,SDB_OPENAL_FREQUENCY);             CheckALError();             alSourceQueueBuffers(openAlSource, 1, &BufID);             CheckALError();         }     }     // функция очищяет все буферы по мере их опустошения, и останавливает проигрывание     // возвращает 1 если еще есть не пустые буферы     char sdb::updateOpenAl(void) {         int processed = 0;         ALuint      BufID;         // Получаем количество отработанных буферов         alGetSourcei(openAlSource, AL_BUFFERS_PROCESSED, &processed);         #if SDB_WITH_DEBUG_MODE == 1             printf("updateOpenAl: %dn",processed);         #endif         // если обработаны все буферы         if (openAlnBuf == processed) {             // Если таковые существуют то             while (processed--) {                 // Исключаем их из очереди                 alSourceUnqueueBuffers(openAlSource, 1, &BufID);                 if (!CheckALError())                     return 0;                 alDeleteBuffers(1, &BufID);                 openAlnBuf--;             }             alSourceStop(openAlSource);             #if SDB_WITH_DEBUG_MODE == 1                 printf("alSourceStop: %dn",openAlnBuf);             #endif             return 0;         }         return 1;     } #endif      // задержка для шин данных. тут генерируется звук     void sdb::busDelay(unsigned short us) {         double Time = (double)us/1000000.0;         double locTime = allTime;         char isFlag = 0;         // создаем wav файл, если он не был создан ранее         if (isCreateWavFileFlag == 0) {             if (isWavFileOutput == 1) {                 isFlag = createWavFile(wavFileName,SDB_FREQUENCY,SDB_BIT,SDB_CANNEL);                 // если файл был успешно открыт, то ставим флаг                 if (isFlag == 1)                     isCreateWavFileFlag = 1;             }             if (isAudioOutput == 1) {                 initOpenAL();                 if (isWavFileOutput == 0)                     isCreateWavFileFlag = 1;             }         }         allTime = allTime + Time;         // если файл был открыт         if (isCreateWavFileFlag == 1)             // начинаем делать сэмплы аудиоданных             while(locTime < allTime) {                 if (switchBuffer == 0) {                     if (posBufferOne >= SDB_BUFFER_MAX) {                         posBufferOne = 0;                         posBufferTwo = 0;                         busDataTwo[posBufferTwo++] = busState;                         isBufferOneFlag = 1;                         switchBuffer = 1;                         if (isWavFileOutput == 1)                             writeDataBlockWavFile(busDataOne,SDB_BUFFER_MAX);                         #if SDB_WITH_OPENAL == 1                             if (isAudioOutput == 1)                                 setBufferOpenAl(busDataOne,SDB_BUFFER_MAX);                         #endif                     } else {                         busDataOne[posBufferOne++] = busState;                     }                 } else                 if (switchBuffer == 1) {                     if (posBufferTwo >= SDB_BUFFER_MAX) {                         posBufferOne = 0;                         posBufferTwo = 0;                         busDataOne[posBufferOne++] = busState;                         isBufferTwoFlag = 1;                         switchBuffer = 0;                         if (isWavFileOutput == 1)                             writeDataBlockWavFile(busDataTwo,SDB_BUFFER_MAX);                         #if SDB_WITH_OPENAL == 1                             if (isAudioOutput == 1)                                 setBufferOpenAl(busDataTwo,SDB_BUFFER_MAX);                         #endif                     } else {                         busDataTwo[posBufferTwo++] = busState;                     }                 }                 posAllBuffer++;                 locTime = locTime + dTime;             }     }       char sdb::createWavFile(char * filename,unsigned long sampleRate,unsigned short bitsPerSample, unsigned short numChannels) {         char type[4];         const unsigned long subchunk1Size = 16;         unsigned long byteRate;         const unsigned short audioFormat = 1;         unsigned short len_str = 0;         char str_filename[512] = {0};         unsigned short i;         // количество байт в одном сэмле одного канала         wavLenDataType = bitsPerSample/8;          wavSubchunk2Size = 0;         wavChunkSize = wavSubchunk2Size + 44 - 8;         // Количество байт на одну выборку         wavBlockAlign = bitsPerSample / (8 * numChannels);         //Количество байт, переданных за секунду воспроизведения.         byteRate = sampleRate * wavBlockAlign;          strcpy(str_filename,filename);         len_str = strlen(str_filename);         if (len_str < 4)             return 0;         // проверка имени файла на наличие расширения .wav         i = 0;         while(i < len_str) {             if (filename[i] == '.' && (i + 3) < len_str) {                 if (((filename[i + 1] == 'w')                     && (filename[i + 2] == 'a')                     && (filename[i + 3] == 'v'))                     ||                     ((filename[i + 1] == 'W')                     && (filename[i + 2] == 'A')                     && (filename[i + 3] == 'V'))) {                     // если имя имеет расширение wav                     break;                 } else {                     if ((i + 3) >= 512)                         return 0;                     filename[i + 1] = 'w';                     filename[i + 2] = 'a';                     filename[i + 3] = 'v';                     len_str = i + 4;                     break;                 }             } else             if ((i + 1) == len_str) {                 if ((i + 3) >= 512)                     return 0;                 filename[i + 1] = '.';                 filename[i + 2] = 'w';                 filename[i + 3] = 'a';                 filename[i + 4] = 'v';                 len_str = i + 5;                 break;             }             i++;         }          type[0] = filename[len_str - 4];         type[1] = filename[len_str - 3];         type[2] = filename[len_str - 2];         type[3] = filename[len_str - 1];         if (type[0]!='.'||type[1]!='w'||type[2]!='a'||type[3]!='v') {             if (type[0]!='.'||type[1]!='W'||type[2]!='A'||type[3]!='V') {                 return 0;             }         }         fpSave=fopen(str_filename,"wb");         type[0]='R';         type[1]='I';         type[2]='F';         type[3]='F';         fwrite(&type,sizeof(char),4,fpSave);         fwrite(&wavChunkSize,sizeof(unsigned long),1,fpSave);          type[0]='W';         type[1]='A';         type[2]='V';         type[3]='E';         fwrite(&type,sizeof(char),4,fpSave);          type[0]='f';         type[1]='m';         type[2]='t';         type[3]=' ';         fwrite(&type,sizeof(char),4,fpSave);         fwrite(&subchunk1Size,sizeof(unsigned long),1,fpSave);         fwrite(&audioFormat,sizeof(unsigned short),1,fpSave);         fwrite(&numChannels,sizeof(unsigned short),1,fpSave);         fwrite(&sampleRate,sizeof(unsigned long),1,fpSave);         fwrite(&byteRate,sizeof(unsigned long),1,fpSave);         fwrite(&wavBlockAlign,sizeof(unsigned short),1,fpSave);         // Количество бит в сэмпле. Так называемая “глубина” или точность звучания. 8 бит, 16 бит и т.д.         fwrite(&bitsPerSample,sizeof(unsigned short),1,fpSave);          type[0]='d';         type[1]='a';         type[2]='t';         type[3]='a';         // subchunk2Id         // Содержит символы “data” (0x64617461 в big-endian представлении)         fwrite(&type, sizeof(char), 4,fpSave);         wavSubchunk2Size = 0;         //Количество байт в области данных.         fwrite(&wavSubchunk2Size, sizeof(unsigned long), 1,fpSave);         return 1;     }      void sdb::writeSampleWavFile(void* data) {         fwrite(data, wavLenDataType, wavBlockAlign, fpSave);         wavSubchunk2Size = wavSubchunk2Size + wavLenDataType*wavBlockAlign;     }      void sdb::writeDataBlockWavFile(void* data, unsigned long len) {         fwrite(data, wavLenDataType, len, fpSave);         wavSubchunk2Size = wavSubchunk2Size + len*wavLenDataType;     }     // данная функция закрывает аудиофайл и записывает количесвто байт данных.     void sdb::closeWavFile(void) {         wavChunkSize = wavSubchunk2Size + 44 - 8;         fseek(fpSave,4,SEEK_SET);         fwrite(&wavChunkSize,4,1,fpSave);         fseek(fpSave,40,SEEK_SET);         fwrite(&wavSubchunk2Size,4,1,fpSave);         fclose(fpSave);     }      // конструктор     sdb::sdb(void) {         openAlnBuf = 0;         wavBlockAlign = 0;         wavSubchunk2Size = 0;         wavChunkSize = 0;         wavLenDataType = 0;         fpSave = NULL;         strcat(wavFileName,SDB_WAV_FILE_NAME);         dTime = 1.0/(double)SDB_OPENAL_FREQUENCY;         allTime = 0.0;         // переключатель буферов на первом буфере         switchBuffer = 0;         // позиция в буферах (сумма)         posAllBuffer = 0;         // позиции в буфере обнуляем         posBufferOne = 0;         posBufferTwo = 0;         isBufferOneFlag = 0;         isBufferTwoFlag = 0;         isCreateWavFileFlag = 0;         busState = SDB_MAX_DATA;         uartSetBaudrate(SDB_UART_BAUDRATE);         uartSetBit(SDB_UART_BIT);         uartSetStopBit(SDB_UART_STOP_BIT);         uartSetParityBit(SDB_UART_PARITY);         recordOn();         playAudioOn();     }      // деструктор     sdb::~sdb() {         if (isCreateWavFileFlag == 1) {             if (posBufferOne > 0) {                 if (isWavFileOutput == 1)                     writeDataBlockWavFile(busDataOne,posBufferOne);                 #if SDB_WITH_OPENAL == 1                     if (isAudioOutput == 1)                         setBufferOpenAl(busDataOne,posBufferTwo);                 #endif              } else             if (posBufferTwo > 0) {                 if (isWavFileOutput == 1)                     writeDataBlockWavFile(busDataTwo,posBufferTwo);                 #if SDB_WITH_OPENAL == 1                     if (isAudioOutput == 1)                         setBufferOpenAl(busDataTwo,posBufferTwo);                 #endif             }             if (isWavFileOutput == 1)                 closeWavFile();             isCreateWavFileFlag = 0;             #if SDB_WITH_OPENAL == 1                 if (isAudioOutput == 1) {                     while (1) {                         // Ждем, когда звук проиграет до конца                         if (updateOpenAl() == 0)                             break;                     }                     closeOpenAlSound();                     destroyOpenAL();                 }             #endif         }     }      // функция передает данные по шине one wire     void sdb::oneWireSendByte(unsigned char data) {         for (register unsigned char i = 0; i < 8; i++) {             if((data & (1 << i)) == 1 << i) {                 busState = 0;                 busDelay(12);                 busState = SDB_MAX_DATA;                 busDelay(65);             } else {                 busState = 0;                 busDelay(65);                 busState = SDB_MAX_DATA;                 busDelay(12);             }         }         busState = SDB_MAX_DATA;     }      // функция передает один байт по шине uart     void sdb::uartSendByte(unsigned char data) {         unsigned short pBit = 0; // переменная для бита четности         // старт бит         busState = SDB_MAX_DATA;         busDelay(uartT);         busState = -SDB_MAX_DATA;         // данные         for (register unsigned char i = 0; i < 8; i++) {             if((data & (1< SDB_UART_BAUDRATE_MAX)             baudrate = SDB_UART_BAUDRATE_MAX;         uartBaudrate = baudrate;         uartT = 1000000 / baudrate;     }      void sdb::uartSetBit(unsigned char bit) {         if (bit > 32)             bit = 32;         if (bit == 0)             bit = 1;         if (bit < 8)             bit = 8;         uartBit = bit;     }      void sdb::uartSetStopBit(unsigned char bit) {         if (bit == 0)             bit = 1;         uartStopBit = bit;     }      void sdb::uartSetParityBit(unsigned char state) {         if (state > 1)             state = 1;         uartParityBit = state;     }      //функция определяет есть ли устройство на шине     void sdb::oneWireReset(void) {         busState = SDB_MAX_DATA;         busDelay(100);         busState = 0;//логический "0"         busDelay(485);//ждем минимум 480мкс         busState = SDB_MAX_DATA;         busDelay(65);//ждем минимум 60мкс и смотрим что на шине         busState = 0;//логический "0"         busDelay(400);         busState = SDB_MAX_DATA;         busDelay(100);     }      // функция останавливает шину 1-wire     void sdb::oneWireStop(void) {         if (isCreateWavFileFlag == 1) {             if (posBufferOne > 0) {                 if (isWavFileOutput == 1)                     writeDataBlockWavFile(busDataOne,posBufferOne);                 #if SDB_WITH_OPENAL == 1                     if (isAudioOutput == 1)                         setBufferOpenAl(busDataOne,posBufferOne);                 #endif             } else             if (posBufferTwo > 0) {                 if (isWavFileOutput == 1)                     writeDataBlockWavFile(busDataTwo,posBufferTwo);                 #if SDB_WITH_OPENAL == 1                     if (isAudioOutput == 1)                         setBufferOpenAl(busDataTwo,posBufferTwo);                 #endif             }             #if SDB_WITH_OPENAL == 1                 while (1) {                     // Ждем, когда звук проиграет до конца                     if (updateOpenAl() == 0)                         break;                 }                 closeOpenAlSound();                 destroyOpenAL();             #endif             if (isWavFileOutput == 1)                 closeWavFile();             isCreateWavFileFlag = 0;         }     }      void sdb::uartStop(void) {         if (isCreateWavFileFlag == 1) {             if (posBufferOne > 0) {                 if (isWavFileOutput == 1)                     writeDataBlockWavFile(busDataOne,posBufferOne);                 #if SDB_WITH_OPENAL == 1                     if (isAudioOutput == 1)                         setBufferOpenAl(busDataOne,posBufferOne);                 #endif             } else             if (posBufferTwo > 0) {                 if (isWavFileOutput == 1)                     writeDataBlockWavFile(busDataTwo,posBufferTwo);                 #if SDB_WITH_OPENAL == 1                     if (isAudioOutput == 1)                         setBufferOpenAl(busDataTwo,posBufferTwo);                 #endif             }             #if SDB_WITH_OPENAL == 1                 if (isAudioOutput == 1) {                     while (1) {                         // Ждем, когда звук проиграет до конца                         if (updateOpenAl() == 0)                             break;                     }                     closeOpenAlSound();                     destroyOpenAL();                 }             #endif             if (isWavFileOutput == 1)                 closeWavFile();             isCreateWavFileFlag = 0;         }     }      void sdb::setWavFileName(char* filename) {         strcat(wavFileName,filename);     }      void sdb::playAudioOn(void) {         if (isCreateWavFileFlag == 0)             isAudioOutput = 1;     }      void sdb::playAudioOff(void) {         if (isCreateWavFileFlag == 0)             isAudioOutput = 0;     }      void sdb::recordOn(void) {         if (isCreateWavFileFlag == 0)             isWavFileOutput = 1;     }      void sdb::recordOff(void) {         if (isCreateWavFileFlag == 0) {             if (isAudioOutput == 1)                 isWavFileOutput = 0;             else                 isWavFileOutput = 1;         }     } 

Файл main.h

#ifndef MAIN_H_INCLUDED #define MAIN_H_INCLUDED  #define LINUX 0x00 #define WINDOWS 0x01  #define RU 0x00 #define EN 0x01  /// Тип операционой системы #define TYPE_OS WINDOWS  /// Язык программы #define LANGUAGE_PROGRAM RU  #define UART_BUS 0x01 #define ONE_WIRE_BUS 0x02  #include  #include "SoundsDigitalBus.h" #include "stdlib.h" #include   #endif // MAIN_H_INCLUDED 

Файл main.cpp

#include "main.h"  sdb soundsDigitalBus;  int main() {     static FILE *fp = NULL; // файл с данными     char strData[512]; // буфер для строк     char strChar = 0; // символ     unsigned char busType; // тип цифровой шины     int strPos = 0; // позиция в строке     int uartBaudrate = 0; // скорость UART     int uartBit = 8;     int uartStopBit = 0;     //int uartParityBit = 0;      #if TYPE_OS==WINDOWS and LANGUAGE_PROGRAM==RU     setlocale(LC_ALL, "Russian");     printf("Введите скорость UART в бод, или укажите 0, если хотите 1-wire.n");     #else     printf("Enter the UART baud rate, or specify 0 if you want 1-wire.n");     #endif     printf("UART Baudrate: ");     memset(strData,0,512);     while(1) {         strChar = getchar();         if ((strChar >= '0') && (strChar <= '9')) {             strData[strPos++] = strChar;         } else             break;     }     uartBaudrate = atoi(strData);     if (uartBaudrate == 0) {         busType = ONE_WIRE_BUS;     } else {         busType = UART_BUS;         soundsDigitalBus.uartSetBaudrate(uartBaudrate);     }     printf("n");     if (busType == UART_BUS) {         #if TYPE_OS==WINDOWS and LANGUAGE_PROGRAM==RU         printf("Введите количество бит UARTn");         #else         printf("Enter the number of bits UART.n");         #endif         printf("UART bit: ");         memset(strData,0,512);         while(1) {             strChar = getchar();             if ((strChar >= '0') && (strChar <= '9')) {                 strData[strPos++] = strChar;             } else                 break;         }         uartBit = atoi(strData);         soundsDigitalBus.uartSetBit(uartBit);         printf("n");         #if TYPE_OS==WINDOWS and LANGUAGE_PROGRAM==RU         printf("Введите количество стоп бит UARTn");         #else         printf("Enter the number of stop bits UART.n");         #endif         printf("UART stop bit: ");         memset(strData,0,512);         while(1) {             strChar = getchar();             if ((strChar >= '0') && (strChar <= '9')) {                 strData[strPos++] = strChar;             } else                 break;         }         uartStopBit = atoi(strData);         soundsDigitalBus.uartSetStopBit(uartStopBit);         printf("n");         #if TYPE_OS==WINDOWS and LANGUAGE_PROGRAM==RU         printf("Использовать бит четности в UART? (Y/n)n");         #else         printf("Use the parity bit in the UART? (Y/n)n");         #endif         strChar = getchar();         if ((strChar == 'n')             || (strChar == 'N')             || (strChar == 'т')             || (strChar == 'Т')) {             soundsDigitalBus.uartSetParityBit(0);             printf("not usedn");         } else {             soundsDigitalBus.uartSetParityBit(1);             printf("Yes, usen");         }         getchar();         printf("n");     }       FILE_M:     printf("n");     #if TYPE_OS==WINDOWS     printf("Укажите файл для преобразования его в запись цифровой шины.n");     printf("Например: D: \ Games \ SR2 \ Rangers.txtn");     printf("Файл: ");     #else     printf("Specify the file to convert it to record digital bus.n");     printf("For example: D: \ Games \ SR2 \ Rangers.txtn");     printf("File: ");     #endif     memset(strData,0,512);     strPos = 0;     while(1) {         strChar = getchar();         if (strChar != 'n') {             strData[strPos++] = strChar;         } else             break;     }     fp = fopen(strData,"rb");     if (fp == NULL) {         printf("n");         #if TYPE_OS==WINDOWS         printf("Ошибка! Файл %s не найден!n",strData);         printf("Поробуйте правильно указать путь до файла.n");         printf("...n");         #else         printf("Error! File %s not found!n",strData);         printf("Try to correctly specify the path to the file.n");         printf("...n");         #endif         getchar();         goto FILE_M;     }     //soundsDigitalBus.setWavFileName(strData);     printf("n"); #if SDB_WITH_OPENAL == 1     #if TYPE_OS==WINDOWS     printf("Воспроизводить аудио во время работы цифровой шины? (Y/n)n");     #else     printf("Play audio while working digital bus? (Y/n)n");     #endif     strChar = getchar();     if ((strChar == 'n')         || (strChar == 'N')         || (strChar == 'т')         || (strChar == 'Т')) {         soundsDigitalBus.playAudioOff();         printf("not usedn");     } else {         soundsDigitalBus.playAudioOn();         printf("Yes, usen");     }     getchar();     printf("n");     #if TYPE_OS==WINDOWS     printf("Записывать аудио во время работы цифровой шины? (Y/n)n");     #else     printf("Record audio while working digital bus? (Y/n)n");     #endif     strChar = getchar();     if ((strChar == 'n')         || (strChar == 'N')         || (strChar == 'т')         || (strChar == 'Т')) {         soundsDigitalBus.recordOff();         printf("not usedn");     } else {         soundsDigitalBus.recordOn();         printf("Yes, usen");     }     getchar(); #else     soundsDigitalBus.recordOn(); #endif     printf("n");     #if TYPE_OS==WINDOWS     printf("Преобразование начато.n");     #else     printf("The transformation started.n");     #endif     unsigned char uartData[8];     if (busType == ONE_WIRE_BUS) {         soundsDigitalBus.oneWireReset();     }     while(1) {         if (fread(uartData,sizeof(unsigned char),1,fp) > 0) {             if (busType == UART_BUS) {                 if (uartBit == 8) {                     soundsDigitalBus.uartSendByte(uartData[0]);                 } else {                     soundsDigitalBus.uartSend(uartData[0]);                 }             } else             if (busType == ONE_WIRE_BUS) {                 soundsDigitalBus.oneWireSendByte(uartData[0]);             }         } else             break;     }     fclose(fp);     if (busType == ONE_WIRE_BUS) {         soundsDigitalBus.oneWireStop();     } else     if (busType == UART_BUS) {         soundsDigitalBus.uartStop();     }     #if TYPE_OS==WINDOWS     printf("Преобразование завершено.n");     #else     printf("Conversion completed.n");     #endif     return 0;     //soundsDigitalBus.oneWireReset();     soundsDigitalBus.uartSetBaudrate(1200);     for (int i = 0; i < 256; i ++) {         for (int len = 0; len < 8; len++) {             soundsDigitalBus.uartSendByte(i);         }         printf("%dn",i);     }     soundsDigitalBus.oneWireStop();     return 0; } 

P.S. Заметил ошибку, что в исходном коде стартовый бит равен логической 1, а не 0, а стоповый равен 0, а не 1. Кому необходимо принципиальное соотвествение звукового сигнала реальности, может исправить ошибку сам.

 
Источник

Читайте также