2015-03-30 23:20:45 +00:00
|
|
|
#include "transmitter.h"
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <fcntl.h>
|
2015-06-26 20:31:24 +00:00
|
|
|
#include <math.h>
|
2015-03-30 23:20:45 +00:00
|
|
|
#include <exception>
|
|
|
|
#include <iostream>
|
|
|
|
|
2015-04-03 13:34:53 +00:00
|
|
|
#define ACCESS(base, offset) *(volatile unsigned int*)((int)base + offset)
|
|
|
|
#define ACCESS64(base, offset) *(volatile unsigned long long*)((int)base + offset)
|
2015-03-30 23:20:45 +00:00
|
|
|
|
2015-04-01 00:31:19 +00:00
|
|
|
Transmitter::Transmitter(double frequency)
|
2015-03-30 23:20:45 +00:00
|
|
|
{
|
|
|
|
int memFd;
|
|
|
|
if ((memFd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
|
2015-04-01 13:00:15 +00:00
|
|
|
std::cout << "Error: sudo privileges are required" << std::endl;
|
2015-03-30 23:20:45 +00:00
|
|
|
throw std::exception();
|
|
|
|
}
|
|
|
|
|
2015-04-04 14:04:08 +00:00
|
|
|
void *peripheralsMap = mmap(NULL, 0x002FFFFF, PROT_READ | PROT_WRITE, MAP_SHARED, memFd, 0x3F000000);
|
2015-03-30 23:20:45 +00:00
|
|
|
close(memFd);
|
2015-04-01 00:31:19 +00:00
|
|
|
if (peripheralsMap == MAP_FAILED) {
|
2015-04-01 13:00:15 +00:00
|
|
|
std::cout << "Error: cannot obtain access to peripherals (mmap error)" << std::endl;
|
2015-03-30 23:20:45 +00:00
|
|
|
throw std::exception();
|
|
|
|
}
|
|
|
|
|
2015-04-01 00:31:19 +00:00
|
|
|
peripherals = (volatile unsigned*)peripheralsMap;
|
|
|
|
|
|
|
|
ACCESS(peripherals, 0x00200000) = (ACCESS(peripherals, 0x00200000) & 0xFFFF8FFF) | (0x01 << 14);
|
2015-04-01 15:55:36 +00:00
|
|
|
ACCESS(peripherals, 0x00101070) = (0x5A << 24) | (0x01 << 9) | (0x01 << 4) | 0x06;
|
2015-04-04 14:04:08 +00:00
|
|
|
|
|
|
|
clockDivisor = (unsigned int)((500 << 12) / frequency + 0.5);
|
2015-03-30 23:20:45 +00:00
|
|
|
}
|
2015-04-01 00:31:19 +00:00
|
|
|
|
2015-04-04 14:04:08 +00:00
|
|
|
void Transmitter::transmit(std::vector<float> *samples, unsigned int sampleRate) {
|
|
|
|
unsigned int offset = 0, length = samples->size(), temp;
|
|
|
|
float *data = &(*samples)[0];
|
2015-04-01 00:31:19 +00:00
|
|
|
|
2015-04-01 15:55:36 +00:00
|
|
|
unsigned long long current = 0;
|
2015-04-03 13:34:53 +00:00
|
|
|
unsigned long long start = ACCESS64(peripherals, 0x00003004);
|
2015-04-01 15:55:36 +00:00
|
|
|
|
2015-04-01 00:31:19 +00:00
|
|
|
while (true) {
|
2015-04-01 21:12:41 +00:00
|
|
|
temp = offset;
|
2015-04-01 15:55:36 +00:00
|
|
|
if (offset >= length) break;
|
2015-04-01 21:12:41 +00:00
|
|
|
|
2015-06-26 20:33:37 +00:00
|
|
|
ACCESS(peripherals, 0x00101074) = (0x5A << 24) | clockDivisor - (int)(round(data[offset] * 16.0));
|
2015-04-01 00:31:19 +00:00
|
|
|
|
2015-04-04 14:04:08 +00:00
|
|
|
while (temp >= offset) {
|
2015-04-01 21:12:41 +00:00
|
|
|
usleep(1);
|
2015-04-01 00:31:19 +00:00
|
|
|
|
2015-04-03 13:34:53 +00:00
|
|
|
current = ACCESS64(peripherals, 0x00003004);
|
|
|
|
offset = (unsigned int)((current - start) * sampleRate / 1000000);
|
2015-04-01 21:12:41 +00:00
|
|
|
}
|
2015-04-01 00:31:19 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-30 23:20:45 +00:00
|
|
|
|
|
|
|
Transmitter::~Transmitter()
|
2015-04-01 00:31:19 +00:00
|
|
|
{
|
|
|
|
ACCESS(peripherals, 0x00101070) = (0x5A << 24);
|
2015-03-30 23:20:45 +00:00
|
|
|
}
|