kopia lustrzana https://github.com/markondej/fm_transmitter
Aarch64 support added
rodzic
b20f4dd85d
commit
c54fc2fcca
15
README.md
15
README.md
|
@ -4,13 +4,22 @@ Use the Raspberry Pi as an FM transmitter. Works on every Raspberry Pi board.
|
|||
Just get an FM receiver, connect a 20 - 40 cm plain wire to the Raspberry Pi's GPIO4 (PIN 7 on GPIO header) to act as an antenna, and you are ready for broadcasting.
|
||||
|
||||
This project uses the general clock output to produce frequency modulated radio communication. It is based on an idea originally presented by [Oliver Mattos and Oskar Weigl](http://icrobotics.co.uk/wiki/index.php/Turning_the_Raspberry_Pi_Into_an_FM_Transmitter) at [PiFM project](http://icrobotics.co.uk/wiki/index.php/Turning_the_Raspberry_Pi_Into_an_FM_Transmitter).
|
||||
## How to use it
|
||||
To use this project you will have to build the executable. First, clone this repository, then use `make` command as shown below:
|
||||
## Installation and usage
|
||||
To use this software you will have to build the executable. First, install required dependencies:
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get install make build-essential
|
||||
```
|
||||
Depending on OS (eg. Ubuntu Server 20.10) installing Broadcom libraries may be also required:
|
||||
```
|
||||
sudo apt-get install libraspberrypi-dev
|
||||
```
|
||||
After installing dependencies clone this repository and use `make` command in order to build executable:
|
||||
```
|
||||
git clone https://github.com/markondej/fm_transmitter
|
||||
cd fm_transmitter
|
||||
make
|
||||
```
|
||||
```
|
||||
After a successful build you can start transmitting by executing the "fm_transmitter" program:
|
||||
```
|
||||
sudo ./fm_transmitter -f 102.0 acoustic_guitar_duet.wav
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
FM Transmitter - use Raspberry Pi as FM transmitter
|
||||
|
||||
Copyright (c) 2020, Marcin Kondej
|
||||
Copyright (c) 2021, Marcin Kondej
|
||||
All rights reserved.
|
||||
|
||||
See https://github.com/markondej/fm_transmitter
|
|
@ -90,7 +90,7 @@ static int mbox_property(int file_desc, void *buf)
|
|||
int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf);
|
||||
|
||||
if (ret_val < 0) {
|
||||
printf("ioctl_set_msg failed:%d\n", ret_val);
|
||||
printf("ioctl_set_msg failed: %d\n", ret_val);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
10
makefile
10
makefile
|
@ -1,13 +1,13 @@
|
|||
EXECUTABLE = fm_transmitter
|
||||
VERSION = 0.9.4
|
||||
VERSION = 0.9.5
|
||||
FLAGS = -Wall -O3 -std=c++11
|
||||
TRANSMITTER = -fno-strict-aliasing -I/opt/vc/include
|
||||
ifeq ($(GPIO21), 1)
|
||||
TRANSMITTER += -DGPIO21
|
||||
endif
|
||||
|
||||
all: main.o mailbox.o sample.o wave_reader.o transmitter.o
|
||||
g++ -L/opt/vc/lib -o $(EXECUTABLE) main.o mailbox.o sample.o wave_reader.o transmitter.o -lm -lpthread -lbcm_host
|
||||
all: fm_transmitter.o mailbox.o sample.o wave_reader.o transmitter.o
|
||||
g++ -L/opt/vc/lib -o $(EXECUTABLE) fm_transmitter.o mailbox.o sample.o wave_reader.o transmitter.o -lm -lpthread -lbcm_host
|
||||
|
||||
mailbox.o: mailbox.c mailbox.h
|
||||
g++ $(FLAGS) -c mailbox.c
|
||||
|
@ -21,8 +21,8 @@ wave_reader.o: wave_reader.cpp wave_reader.hpp
|
|||
transmitter.o: transmitter.cpp transmitter.hpp
|
||||
g++ $(FLAGS) $(TRANSMITTER) -c transmitter.cpp
|
||||
|
||||
main.o: main.cpp
|
||||
g++ $(FLAGS) -DVERSION=\"$(VERSION)\" -DEXECUTABLE=\"$(EXECUTABLE)\" -c main.cpp
|
||||
fm_transmitter.o: fm_transmitter.cpp
|
||||
g++ $(FLAGS) -DVERSION=\"$(VERSION)\" -DEXECUTABLE=\"$(EXECUTABLE)\" -c fm_transmitter.cpp
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
FM Transmitter - use Raspberry Pi as FM transmitter
|
||||
|
||||
Copyright (c) 2020, Marcin Kondej
|
||||
Copyright (c) 2021, Marcin Kondej
|
||||
All rights reserved.
|
||||
|
||||
See https://github.com/markondej/fm_transmitter
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
FM Transmitter - use Raspberry Pi as FM transmitter
|
||||
|
||||
Copyright (c) 2020, Marcin Kondej
|
||||
Copyright (c) 2021, Marcin Kondej
|
||||
All rights reserved.
|
||||
|
||||
See https://github.com/markondej/fm_transmitter
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
FM Transmitter - use Raspberry Pi as FM transmitter
|
||||
|
||||
Copyright (c) 2020, Marcin Kondej
|
||||
Copyright (c) 2021, Marcin Kondej
|
||||
All rights reserved.
|
||||
|
||||
See https://github.com/markondej/fm_transmitter
|
||||
|
@ -127,13 +127,13 @@ class Peripherals
|
|||
static Peripherals instance;
|
||||
return instance;
|
||||
}
|
||||
inline uint32_t GetPhysicalAddress(volatile void *object) const {
|
||||
return PERIPHERALS_PHYS_BASE + (reinterpret_cast<uint32_t>(object) - reinterpret_cast<uint32_t>(peripherals));
|
||||
inline uintptr_t GetPhysicalAddress(volatile void *object) const {
|
||||
return PERIPHERALS_PHYS_BASE + (reinterpret_cast<uintptr_t>(object) - reinterpret_cast<uintptr_t>(peripherals));
|
||||
}
|
||||
inline uint32_t GetVirtualAddress(uint32_t offset) const {
|
||||
return reinterpret_cast<uint32_t>(peripherals) + offset;
|
||||
inline uintptr_t GetVirtualAddress(uintptr_t offset) const {
|
||||
return reinterpret_cast<uintptr_t>(peripherals) + offset;
|
||||
}
|
||||
inline static uint32_t GetVirtualBaseAddress() {
|
||||
inline static uintptr_t GetVirtualBaseAddress() {
|
||||
return (bcm_host_get_peripheral_size() == BCM2838_PERI_VIRT_BASE) ? BCM2838_PERI_VIRT_BASE : bcm_host_get_peripheral_address();
|
||||
}
|
||||
inline static float GetClockFrequency() {
|
||||
|
@ -191,15 +191,15 @@ class AllocatedMemory
|
|||
AllocatedMemory(const AllocatedMemory &) = delete;
|
||||
AllocatedMemory(AllocatedMemory &&) = delete;
|
||||
AllocatedMemory &operator=(const AllocatedMemory &) = delete;
|
||||
inline uint32_t GetPhysicalAddress(volatile void *object) const {
|
||||
return (memSize) ? memAddress + (reinterpret_cast<uint32_t>(object) - reinterpret_cast<uint32_t>(memAllocated)) : 0x00000000;
|
||||
inline uintptr_t GetPhysicalAddress(volatile void *object) const {
|
||||
return (memSize) ? memAddress + (reinterpret_cast<uintptr_t>(object) - reinterpret_cast<uintptr_t>(memAllocated)) : 0x00000000;
|
||||
}
|
||||
inline uint32_t GetAddress() const {
|
||||
return reinterpret_cast<uint32_t>(memAllocated);
|
||||
inline uintptr_t GetBaseAddress() const {
|
||||
return reinterpret_cast<uintptr_t>(memAllocated);
|
||||
}
|
||||
private:
|
||||
unsigned memSize, memHandle;
|
||||
uint32_t memAddress;
|
||||
uintptr_t memAddress;
|
||||
void *memAllocated;
|
||||
int mBoxFd;
|
||||
};
|
||||
|
@ -220,7 +220,7 @@ class Device
|
|||
class ClockDevice : public Device
|
||||
{
|
||||
public:
|
||||
ClockDevice(uint32_t clockAddress, unsigned divisor) {
|
||||
ClockDevice(uintptr_t clockAddress, unsigned divisor) {
|
||||
clock = reinterpret_cast<ClockRegisters *>(peripherals->GetVirtualAddress(clockAddress));
|
||||
clock->ctl = (0x5a << 24) | 0x06;
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(1000));
|
||||
|
@ -382,7 +382,7 @@ void Transmitter::TransmitViaCpu(WaveReader &reader, ClockOutput &output, unsign
|
|||
std::this_thread::sleep_for(std::chrono::microseconds(BUFFER_TIME / 2));
|
||||
|
||||
auto finally = [&]() {
|
||||
stopped = true;
|
||||
stopped = true;
|
||||
transmitterThread.join();
|
||||
samples.clear();
|
||||
};
|
||||
|
@ -416,7 +416,7 @@ void Transmitter::TransmitViaDma(WaveReader &reader, ClockOutput &output, unsign
|
|||
throw std::runtime_error("DMA channel number out of range (0 - 15)");
|
||||
}
|
||||
|
||||
AllocatedMemory allocated(sizeof(uint32_t) * (bufferSize) + sizeof(DMAControllBlock) * (2 * bufferSize) + sizeof(uint32_t));
|
||||
AllocatedMemory allocated(sizeof(uint32_t) * bufferSize + sizeof(DMAControllBlock) * (2 * bufferSize) + sizeof(uint32_t));
|
||||
|
||||
std::vector<Sample> samples = reader.GetSamples(bufferSize, stopped);
|
||||
if (samples.empty()) {
|
||||
|
@ -434,12 +434,12 @@ void Transmitter::TransmitViaDma(WaveReader &reader, ClockOutput &output, unsign
|
|||
|
||||
unsigned i, cbOffset = 0;
|
||||
|
||||
volatile DMAControllBlock *dmaCb = reinterpret_cast<DMAControllBlock *>(allocated.GetAddress());
|
||||
volatile uint32_t *clkDiv = reinterpret_cast<uint32_t *>(reinterpret_cast<uint32_t>(dmaCb) + 2 * sizeof(DMAControllBlock) * bufferSize);
|
||||
volatile uint32_t *pwmFifoData = reinterpret_cast<uint32_t *>(reinterpret_cast<uint32_t>(clkDiv) + sizeof(uint32_t) * bufferSize);
|
||||
volatile DMAControllBlock *dmaCb = reinterpret_cast<DMAControllBlock *>(allocated.GetBaseAddress());
|
||||
volatile uint32_t *clkDiv = reinterpret_cast<uint32_t *>(reinterpret_cast<uintptr_t>(dmaCb) + 2 * sizeof(DMAControllBlock) * bufferSize);
|
||||
volatile uint32_t *pwmFifoData = reinterpret_cast<uint32_t *>(reinterpret_cast<uintptr_t>(clkDiv) + sizeof(uint32_t) * bufferSize);
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
float value = samples[i].GetMonoValue();
|
||||
clkDiv[i] = (0x5a << 24) | (0xffffff & (clockDivisor - static_cast<int>(round(value * divisorRange))));
|
||||
clkDiv[i] = (0x5a << 24) | (0xffffff & (clockDivisor - static_cast<int32_t>(round(value * divisorRange))));
|
||||
dmaCb[cbOffset].transferInfo = (0x01 << 26) | (0x01 << 3);
|
||||
dmaCb[cbOffset].srcAddress = allocated.GetPhysicalAddress(&clkDiv[i]);
|
||||
dmaCb[cbOffset].dstAddress = peripherals.GetPhysicalAddress(&output.GetDivisor());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
FM Transmitter - use Raspberry Pi as FM transmitter
|
||||
|
||||
Copyright (c) 2020, Marcin Kondej
|
||||
Copyright (c) 2021, Marcin Kondej
|
||||
All rights reserved.
|
||||
|
||||
See https://github.com/markondej/fm_transmitter
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
FM Transmitter - use Raspberry Pi as FM transmitter
|
||||
|
||||
Copyright (c) 2020, Marcin Kondej
|
||||
Copyright (c) 2021, Marcin Kondej
|
||||
All rights reserved.
|
||||
|
||||
See https://github.com/markondej/fm_transmitter
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
FM Transmitter - use Raspberry Pi as FM transmitter
|
||||
|
||||
Copyright (c) 2020, Marcin Kondej
|
||||
Copyright (c) 2021, Marcin Kondej
|
||||
All rights reserved.
|
||||
|
||||
See https://github.com/markondej/fm_transmitter
|
||||
|
|
Ładowanie…
Reference in New Issue