kopia lustrzana https://github.com/markondej/fm_transmitter
commit
13ee37062c
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
fm_transmitter - use Raspberry Pi as FM transmitter
|
||||
|
||||
Copyright (c) 2019, Marcin Kondej
|
||||
All rights reserved.
|
||||
|
||||
See https://github.com/markondej/fm_transmitter
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are
|
||||
permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "error_reporter.hpp"
|
||||
|
||||
ErrorReporter::ErrorReporter() :
|
||||
errorMessage(std::string())
|
||||
{
|
||||
}
|
||||
|
||||
ErrorReporter::ErrorReporter(std::string message) :
|
||||
errorMessage(message)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorReporter::~ErrorReporter() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char *ErrorReporter::what() const throw()
|
||||
{
|
||||
return errorMessage.c_str();
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
fm_transmitter - use Raspberry Pi as FM transmitter
|
||||
|
||||
Copyright (c) 2019, Marcin Kondej
|
||||
All rights reserved.
|
||||
|
||||
See https://github.com/markondej/fm_transmitter
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are
|
||||
permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ERROR_REPORTER_HPP
|
||||
#define ERROR_REPORTER_HPP
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
class ErrorReporter : public std::exception
|
||||
{
|
||||
public:
|
||||
ErrorReporter();
|
||||
ErrorReporter(std::string message);
|
||||
virtual ~ErrorReporter() throw();
|
||||
|
||||
virtual const char *what() const throw();
|
||||
protected:
|
||||
std::string errorMessage;
|
||||
};
|
||||
|
||||
#endif // ERROR_REPORTER_HPP
|
7
makefile
7
makefile
|
@ -2,14 +2,11 @@ EXECUTABLE = fm_transmitter
|
|||
VERSION = 0.9.3
|
||||
FLAGS = -Wall -O3 -std=c++11
|
||||
|
||||
all: main.o mailbox.o error_reporter.o sample.o wave_reader.o transmitter.o
|
||||
g++ -L/opt/vc/lib -lm -lpthread -lbcm_host -o $(EXECUTABLE) main.o mailbox.o sample.o error_reporter.o wave_reader.o transmitter.o
|
||||
all: main.o mailbox.o sample.o wave_reader.o transmitter.o
|
||||
g++ -L/opt/vc/lib -lm -lpthread -lbcm_host -o $(EXECUTABLE) main.o mailbox.o sample.o wave_reader.o transmitter.o
|
||||
|
||||
mailbox.o: mailbox.c mailbox.h
|
||||
g++ $(FLAGS) -c mailbox.c
|
||||
|
||||
error_reporter.o: error_reporter.cpp error_reporter.hpp
|
||||
g++ $(FLAGS) -c error_reporter.cpp
|
||||
|
||||
sample.o: sample.cpp sample.hpp
|
||||
g++ $(FLAGS) -c sample.cpp
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
*/
|
||||
|
||||
#include "transmitter.hpp"
|
||||
#include "error_reporter.hpp"
|
||||
#include "mailbox.h"
|
||||
#include <bcm_host.h>
|
||||
#include <thread>
|
||||
|
@ -131,13 +130,13 @@ Transmitter::Transmitter()
|
|||
{
|
||||
int memFd;
|
||||
if ((memFd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
|
||||
throw ErrorReporter("Cannot open /dev/mem (permission denied)");
|
||||
throw std::runtime_error("Cannot open /dev/mem (permission denied)");
|
||||
}
|
||||
|
||||
peripherals = mmap(nullptr, getPeripheralsSize(), PROT_READ | PROT_WRITE, MAP_SHARED, memFd, getPeripheralsVirtBaseAddress());
|
||||
close(memFd);
|
||||
if (peripherals == MAP_FAILED) {
|
||||
throw ErrorReporter("Cannot obtain access to peripherals (mmap error)");
|
||||
throw std::runtime_error("Cannot obtain access to peripherals (mmap error)");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,7 +273,7 @@ void Transmitter::closeClockOutput(volatile ClockRegisters *clock)
|
|||
void Transmitter::transmit(WaveReader &reader, double frequency, double bandwidth, uint8_t dmaChannel, bool preserveCarrierOnExit)
|
||||
{
|
||||
if (transmitting) {
|
||||
throw ErrorReporter("Cannot play, transmitter already in use");
|
||||
throw std::runtime_error("Cannot play, transmitter already in use");
|
||||
}
|
||||
|
||||
transmitting = true;
|
||||
|
@ -298,7 +297,7 @@ void Transmitter::transmit(WaveReader &reader, double frequency, double bandwidt
|
|||
} else {
|
||||
transmitViaCpu(reader, bufferSize);
|
||||
}
|
||||
} catch (ErrorReporter &catched) {
|
||||
} catch (std::runtime_error &catched) {
|
||||
closeClockOutput(output);
|
||||
throw catched;
|
||||
}
|
||||
|
@ -318,9 +317,9 @@ void Transmitter::transmitViaCpu(WaveReader &reader, uint32_t bufferSize)
|
|||
sampleOffset = 0;
|
||||
buffer = samples;
|
||||
|
||||
bool eof = samples->size() < bufferSize, exceptionCatched = false;
|
||||
bool eof = samples->size() < bufferSize, errorCatched = false;
|
||||
std::thread txThread(Transmitter::transmitThread);
|
||||
ErrorReporter exception;
|
||||
std::string errorMessage;
|
||||
|
||||
usleep(BUFFER_TIME / 2);
|
||||
|
||||
|
@ -339,24 +338,24 @@ void Transmitter::transmitViaCpu(WaveReader &reader, uint32_t bufferSize)
|
|||
}
|
||||
usleep(BUFFER_TIME / 2);
|
||||
}
|
||||
} catch (ErrorReporter &catched) {
|
||||
exceptionCatched = true;
|
||||
exception = catched;
|
||||
} catch (std::runtime_error &catched) {
|
||||
errorMessage = std::string(catched.what());
|
||||
errorCatched = true;
|
||||
}
|
||||
transmitting = false;
|
||||
txThread.join();
|
||||
if (buffer != nullptr) {
|
||||
delete buffer;
|
||||
}
|
||||
if (exceptionCatched) {
|
||||
throw exception;
|
||||
if (errorCatched) {
|
||||
throw std::runtime_error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
void Transmitter::transmitViaDma(WaveReader &reader, uint32_t bufferSize, uint8_t dmaChannel)
|
||||
{
|
||||
if (dmaChannel > 15) {
|
||||
throw ErrorReporter("DMA channel number out of range (0 - 15)");
|
||||
throw std::runtime_error("DMA channel number out of range (0 - 15)");
|
||||
}
|
||||
|
||||
std::vector<Sample> *samples = reader.getSamples(bufferSize, transmitting);
|
||||
|
@ -372,7 +371,7 @@ void Transmitter::transmitViaDma(WaveReader &reader, uint32_t bufferSize, uint8_
|
|||
AllocatedMemory dmaMemory = allocateMemory(sizeof(uint32_t) * (bufferSize + 1) + sizeof(DMAControllBlock) * (2 * bufferSize));
|
||||
if (!dmaMemory.size) {
|
||||
delete samples;
|
||||
throw ErrorReporter("Cannot allocate memory");
|
||||
throw std::runtime_error("Cannot allocate memory");
|
||||
}
|
||||
|
||||
volatile PWMRegisters *pwm = initPwmController();
|
||||
|
@ -412,8 +411,8 @@ void Transmitter::transmitViaDma(WaveReader &reader, uint32_t bufferSize, uint8_
|
|||
delete samples;
|
||||
|
||||
volatile DMARegisters *dma = startDma(dmaMemory, dmaCb, dmaChannel);
|
||||
bool exceptionCatched = false;
|
||||
ErrorReporter exception;
|
||||
bool errorCatched = false;
|
||||
std::string errorMessage;
|
||||
usleep(BUFFER_TIME / 4);
|
||||
|
||||
try {
|
||||
|
@ -437,9 +436,9 @@ void Transmitter::transmitViaDma(WaveReader &reader, uint32_t bufferSize, uint8_
|
|||
}
|
||||
delete samples;
|
||||
}
|
||||
} catch (ErrorReporter &catched) {
|
||||
exceptionCatched = true;
|
||||
exception = catched;
|
||||
} catch (std::runtime_error &catched) {
|
||||
errorMessage = std::string(catched.what());
|
||||
errorCatched = true;
|
||||
}
|
||||
|
||||
cbOffset = (cbOffset < 2 * bufferSize) ? cbOffset : 0;
|
||||
|
@ -454,8 +453,8 @@ void Transmitter::transmitViaDma(WaveReader &reader, uint32_t bufferSize, uint8_
|
|||
freeMemory(dmaMemory);
|
||||
transmitting = false;
|
||||
|
||||
if (exceptionCatched) {
|
||||
throw exception;
|
||||
if (errorCatched) {
|
||||
throw std::runtime_error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
*/
|
||||
|
||||
#include "wave_reader.hpp"
|
||||
#include "error_reporter.hpp"
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -48,13 +48,13 @@ WaveReader::WaveReader(std::string filename, bool &continueFlag) :
|
|||
}
|
||||
|
||||
if (fileDescriptor == -1) {
|
||||
throw ErrorReporter(std::string("Cannot open ") + getFilename() + std::string(", file does not exist"));
|
||||
throw std::runtime_error(std::string("Cannot open ") + getFilename() + std::string(", file does not exist"));
|
||||
}
|
||||
|
||||
try {
|
||||
readData(sizeof(PCMWaveHeader::chunkID) + sizeof(PCMWaveHeader::chunkSize) + sizeof(PCMWaveHeader::format), true, continueFlag);
|
||||
if ((std::string(reinterpret_cast<char *>(header.chunkID), 4) != std::string("RIFF")) || (std::string(reinterpret_cast<char *>(header.format), 4) != std::string("WAVE"))) {
|
||||
throw ErrorReporter(std::string("Error while opening ") + getFilename() + std::string(", WAVE file expected"));
|
||||
throw std::runtime_error(std::string("Error while opening ") + getFilename() + std::string(", WAVE file expected"));
|
||||
}
|
||||
|
||||
readData(sizeof(PCMWaveHeader::subchunk1ID) + sizeof(PCMWaveHeader::subchunk1Size), true, continueFlag);
|
||||
|
@ -62,7 +62,7 @@ WaveReader::WaveReader(std::string filename, bool &continueFlag) :
|
|||
sizeof(PCMWaveHeader::sampleRate) + sizeof(PCMWaveHeader::byteRate) + sizeof(PCMWaveHeader::blockAlign) +
|
||||
sizeof(PCMWaveHeader::bitsPerSample);
|
||||
if ((std::string(reinterpret_cast<char *>(header.subchunk1ID), 4) != std::string("fmt ")) || (header.subchunk1Size < subchunk1MinSize)) {
|
||||
throw ErrorReporter(std::string("Error while opening ") + getFilename() + std::string(", data corrupted"));
|
||||
throw std::runtime_error(std::string("Error while opening ") + getFilename() + std::string(", data corrupted"));
|
||||
}
|
||||
|
||||
readData(header.subchunk1Size, true, continueFlag);
|
||||
|
@ -70,14 +70,14 @@ WaveReader::WaveReader(std::string filename, bool &continueFlag) :
|
|||
(header.byteRate != (header.bitsPerSample >> 3) * header.channels * header.sampleRate) ||
|
||||
(header.blockAlign != (header.bitsPerSample >> 3) * header.channels) ||
|
||||
(((header.bitsPerSample >> 3) != 1) && ((header.bitsPerSample >> 3) != 2))) {
|
||||
throw ErrorReporter(std::string("Error while opening ") + getFilename() + std::string(", unsupported WAVE format"));
|
||||
throw std::runtime_error(std::string("Error while opening ") + getFilename() + std::string(", unsupported WAVE format"));
|
||||
}
|
||||
|
||||
readData(sizeof(PCMWaveHeader::subchunk2ID) + sizeof(PCMWaveHeader::subchunk2Size), true, continueFlag);
|
||||
if (std::string(reinterpret_cast<char *>(header.subchunk2ID), 4) != std::string("data")) {
|
||||
throw ErrorReporter(std::string("Error while opening ") + getFilename() + std::string(", data corrupted"));
|
||||
throw std::runtime_error(std::string("Error while opening ") + getFilename() + std::string(", data corrupted"));
|
||||
}
|
||||
} catch (ErrorReporter &error) {
|
||||
} catch (std::runtime_error &error) {
|
||||
if (fileDescriptor != STDIN_FILENO) {
|
||||
close(fileDescriptor);
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ std::vector<uint8_t> *WaveReader::readData(uint32_t bytesToRead, bool headerByte
|
|||
if (((bytes == -1) && ((fileDescriptor != STDIN_FILENO) || (errno != EAGAIN))) ||
|
||||
((static_cast<uint32_t>(bytes) < bytesToRead) && headerBytes && (fileDescriptor != STDIN_FILENO))) {
|
||||
delete data;
|
||||
throw ErrorReporter(std::string("Error while opening ") + getFilename() + std::string(", data corrupted"));
|
||||
throw std::runtime_error(std::string("Error while opening ") + getFilename() + std::string(", data corrupted"));
|
||||
}
|
||||
if (bytes > 0) {
|
||||
bytesRead += bytes;
|
||||
|
@ -128,9 +128,9 @@ std::vector<uint8_t> *WaveReader::readData(uint32_t bytesToRead, bool headerByte
|
|||
|
||||
if (headerBytes) {
|
||||
if (data == NULL) {
|
||||
throw ErrorReporter("Cannot obtain header, program interrupted");
|
||||
throw std::runtime_error("Cannot obtain header, program interrupted");
|
||||
}
|
||||
memcpy(&(reinterpret_cast<uint8_t *>(&header))[headerOffset], &(*data)[0], bytesRead);
|
||||
std::memcpy(&(reinterpret_cast<uint8_t *>(&header))[headerOffset], &(*data)[0], bytesRead);
|
||||
headerOffset += bytesRead;
|
||||
delete data;
|
||||
data = NULL;
|
||||
|
@ -156,7 +156,7 @@ std::vector<Sample> *WaveReader::getSamples(uint32_t quantity, bool &continueFla
|
|||
|
||||
try {
|
||||
data = readData(bytesToRead, false, continueFlag);
|
||||
} catch (ErrorReporter &error) {
|
||||
} catch (std::runtime_error &error) {
|
||||
delete samples;
|
||||
throw error;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue