Porównaj commity

...

11 Commity

Autor SHA1 Wiadomość Data
David Michaeli ffbd7afee8 example fixed 2024-03-16 12:28:03 +02:00
David Michaeli 1b34c568ff update firmware for tx control signals output on pmod
added dsp flow example
2024-03-16 12:14:41 +02:00
David Michaeli 21a97334a7 rearranged api examples 2024-03-14 23:45:09 +02:00
David Michaeli f8793a7ffe firmware removed debug on LEDs
driver cleanup unused variables
2024-03-14 23:26:20 +02:00
David Michaeli 96828b4bcc firmware update - syncs, ioctrl, smi_ctrl(dir and channel)
fpga driver update
smi_stream_driver update thanks to @matteoserva great work
2024-03-14 22:59:38 +02:00
David Michaeli 80faa75c1f
Merge pull request #192 from matteoserva/new_kernel_module
Improved kernel module, Thanks a lot!
2024-03-14 22:40:41 +02:00
matteo serva 4577e41b61 Revert "moved buffers initialization"
This reverts commit baccfb4805.
2024-03-13 21:41:38 +01:00
matteo serva 26fe48f53d fixed driver lockup at channel 0 RX. The fpga firmware
was using the smi address pins to determine which channel can write the complex_fifo.
The read side of the complex fifo is connected to the DREQ pin of the SMI interface on the raspberry.
The address pins on the smi interface are at logic 1 when no transfer is in progress.

This caused a deadlock condition: the SMI address pin is at 1, so the fifo cannot be filled, so the DREQ cannot be asserted and the SMI cannot start reading data.
2024-03-13 20:42:30 +01:00
matteo serva baccfb4805 moved buffers initialization 2024-03-13 20:22:36 +01:00
matteo serva 7c6f853dc1 fixing spurious wakeup while waiting for write pipe 2024-03-08 09:03:11 +01:00
matteo serva 75d25800bc Improved kernel module:
- Using cyclic dma for data transfer
- removed kernel threads. Now everything done in callbacks
- keeping multiple transactions running to avoid delays
- discarding data if too late
- logging the module performance
- cleaned out the code
- modified communication with userspace to fix polling
- removed redundant locks
- changed buffers behavior to improve efficiency
- fixed compatibility with latest raspbian kernel
2024-03-02 22:39:21 +01:00
43 zmienionych plików z 40557 dodań i 36801 usunięć

Wyświetl plik

@ -15,7 +15,7 @@ USERSPACE_SMI_DIR="../software/libcariboulite/src/caribou_smi/kernel"
## FUNCTIONS
install() {
local mtu_mult=${1:-6}
local mtu_mult=${1:-16}
local dir_offs=${2:-2}
local ch_offs=${3:-3}

Plik diff jest za duży Load Diff

Wyświetl plik

@ -12,30 +12,30 @@ int main ()
// board detection
bool detected = cariboulite_detect_connected_board(&hw_ver, hw_name, hw_uuid);
if (detected) printf("Detection: %d, HWVer: %d, HWName: %s, UUID: %s\n", detected, hw_ver, hw_name, hw_uuid);
else
else
{
printf("No board detection, Exiting\n");
return 0;
}
// library version
cariboulite_get_lib_version(&version);
printf("Version: %02d.%02d.%02d\n", version.major_version, version.minor_version, version.revision);
// init
cariboulite_init(false, cariboulite_log_level_none);
cariboulite_init(false, cariboulite_log_level_none);
// board serial number
serial_number = cariboulite_get_sn();
printf("Serial Number: %08X\n", serial_number);
// channels names and freqs
char ch_name[64];
int ch_num_ranges;
float low_freq_vec[3]; // the actual size determined by ch_num_ranges but here we just statically allocated
float high_freq_vec[3];
int channels[2] = {cariboulite_channel_s1g, cariboulite_channel_hif};
for (int ch_ind = 0; ch_ind < 2; ch_ind ++)
{
cariboulite_get_channel_name(channels[ch_ind], ch_name, sizeof(ch_name));
@ -43,11 +43,10 @@ int main ()
printf("Channel: %d, Name: %s, Num. Freq. Ranges: %d\n", channels[ch_ind], ch_name, ch_num_ranges);
cariboulite_get_frequency_limits(channels[ch_ind], low_freq_vec, high_freq_vec, NULL);
for (int i = 0; i < ch_num_ranges; i++)
{
{
printf(" Range %d: [%.2f, %.2f]\n", i, low_freq_vec[i], high_freq_vec[i]);
}
}
cariboulite_close();
return 0;
return 0;
}

Wyświetl plik

@ -21,7 +21,7 @@ void detectBoard()
CaribouLite::SysVersion ver;
std::string name;
std::string guid;
if (CaribouLite::DetectBoard(&ver, name, guid))
{
std::cout << "Detected Version: " << CaribouLite::GetSystemVersionStr(ver) << ", Name: " << name << ", GUID: " << guid << std::endl;
@ -29,21 +29,21 @@ void detectBoard()
else
{
std::cout << "Undetected CaribouLite!" << std::endl;
}
}
}
// Calculate the RSSI
float RSSI(const std::complex<float>* signal, size_t num_of_samples)
{
if (num_of_samples == 0)
if (num_of_samples == 0)
{
return 0.0f;
}
float sum_of_squares = 0.0f;
for (size_t i = 0; i < num_of_samples && i < num_of_samples; ++i)
for (size_t i = 0; i < num_of_samples && i < num_of_samples; ++i)
{
float vrms = std::norm(signal[i]);
float vrms = std::norm(signal[i]);
sum_of_squares += vrms * vrms / 100.0;
}
@ -61,10 +61,9 @@ void receivedSamples(CaribouLiteRadio* radio, const std::complex<float>* samples
std::cout << "[" << samples[i].real() << ", " << samples[i].imag() << "]";
}
std::cout << std::endl;*/
std::cout << "Radio: " << radio->GetRadioName() << " Received " << std::dec << num_samples << " samples"
<< "RSSI: " << RSSI(samples, num_samples) << " dBm" << std::endl;
}
@ -73,21 +72,21 @@ int main ()
{
// try detecting the board before getting the instance
detectBoard();
// get driver instance - use "CaribouLite&" rather than "CaribouLite" (ref)
CaribouLite &cl = CaribouLite::GetInstance();
// print the info after connecting
printInfo(cl);
// get the radios
CaribouLiteRadio *s1g = cl.GetRadioChannel(CaribouLiteRadio::RadioType::S1G);
CaribouLiteRadio *hif = cl.GetRadioChannel(CaribouLiteRadio::RadioType::HiF);
// write radio information
std::cout << "First Radio Name: " << s1g->GetRadioName() << " MtuSize: " << std::dec << s1g->GetNativeMtuSample() << " Samples" << std::endl;
std::cout << "First Radio Name: " << hif->GetRadioName() << " MtuSize: " << std::dec << hif->GetNativeMtuSample() << " Samples" << std::endl;
std::vector<CaribouLiteFreqRange> range_s1g = s1g->GetFrequencyRange();
std::vector<CaribouLiteFreqRange> range_hif = hif->GetFrequencyRange();
std::cout << "S1G Frequency Regions:" << std::endl;
@ -95,13 +94,13 @@ int main ()
{
std::cout << " " << i << ": " << range_s1g[i] << std::endl;
}
std::cout << "HiF Frequency Regions:" << std::endl;
for (int i = 0; i < range_hif.size(); i++)
{
std::cout << " " << i << ": " << range_hif[i] << std::endl;
}
// start receiving until enter pressed on 900MHz
int num = 2;
while (num --)
@ -115,13 +114,12 @@ int main ()
{
std::cout << "The specified freq couldn't be used" << std::endl;
}
s1g->SetRxGain(0);
s1g->SetAgc(false);
s1g->StartReceiving(receivedSamples);
getchar();
try
{
hif->SetFrequency(2400000000);
@ -134,11 +132,10 @@ int main ()
hif->SetRxGain(0);
hif->SetAgc(false);
hif->StartReceiving(receivedSamples);
getchar();
}
hif->StopReceiving();
return 0;
}

Wyświetl plik

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.2)
project(test_app)
# Find the package using pkg-config
find_package(PkgConfig REQUIRED)
pkg_check_modules(CARIBOULITE REQUIRED cariboulite)
# Add the executable
add_executable(test_app main.cpp)
# Include directories from the cariboulite package
target_include_directories(test_app PRIVATE ${CARIBOULITE_INCLUDE_DIRS})
# Link against the cariboulite library
target_link_libraries(test_app PRIVATE ${CARIBOULITE_LIBRARIES} -lcariboulite pthread)

Wyświetl plik

@ -0,0 +1,165 @@
#ifndef __CIRC_BUFFER_H__
#define __CIRC_BUFFER_H__
#include <string.h>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <atomic>
#define IS_POWER_OF_2(x) (!((x) == 0) && !((x) & ((x) - 1)))
#define MIN(x,y) ((x)>(y)?(y):(x))
template <class T>
class circular_buffer {
public:
circular_buffer(size_t size, bool override_write = true, bool block_read = true)
{
max_size_ = size;
if (!IS_POWER_OF_2(max_size_))
{
max_size_ = next_power_of_2(max_size_);
}
buf_ = new T[max_size_];
override_write_ = override_write;
block_read_ = block_read;
}
~circular_buffer()
{
std::unique_lock<std::mutex> lock(mutex_);
delete []buf_;
}
size_t put(const T *data, size_t length)
{
std::lock_guard<std::mutex> lock(mutex_);
if ((max_size_ - size()) < length && override_write_)
{
// pop the amount of data the is needed
tail_ += length - (max_size_ - size());
}
size_t len = MIN(length, max_size_ - head_ + tail_);
auto l = MIN(len, max_size_ - (head_ & (max_size_ - 1)));
memcpy(buf_ + (head_ & (max_size_ - 1)), data, l * sizeof(T));
memcpy(buf_, data + l, (len - l) * sizeof(T));
head_ += len;
if (block_read_)
{
cond_var_.notify_one();
}
return len;
}
size_t get(T *data, size_t length, int timeout_us = 100000)
{
std::unique_lock<std::mutex> lock(mutex_);
if (block_read_)
{
cond_var_.wait_for(lock, std::chrono::microseconds(timeout_us), [&]()
{
// Acquire the lock only if
// we got enough items
return size() >= length;
});
if (size() == 0)
{
return 0;
}
}
size_t len = MIN(length, head_ - tail_);
auto l = MIN(len, max_size_ - (tail_ & (max_size_ - 1)));
if (data != NULL)
{
memcpy(data, buf_ + (tail_ & (max_size_ - 1)), l * sizeof(T));
memcpy(data + l, buf_, (len - l) * sizeof(T));
}
tail_ += len;
return len;
}
void put(T item)
{
put(&item, 1);
}
T get()
{
T item;
get(&item, 1);
return item;
}
void reset()
{
std::unique_lock<std::mutex> lock(mutex_);
head_ = tail_ = 0;
}
inline bool empty()
{
return head_ == tail_;
}
inline bool full()
{
return size() == capacity();
}
inline size_t capacity() const
{
return max_size_;
}
size_t size()
{
return (head_ - tail_);
}
void print_buffer()
{
std::unique_lock<std::mutex> lock(mutex_);
size_t t = tail_;
int i = 0;
while (t < head_)
{
printf("%d => %d\n", i++, (int)buf_[t++&(max_size_-1)]);
}
}
private:
uint32_t next_power_of_2 (uint32_t x)
{
uint32_t power = 1;
while(power < x)
{
power <<= 1;
}
return power;
}
private:
std::mutex mutex_;
std::condition_variable cond_var_;
T* buf_;
size_t head_ = 0;
size_t tail_ = 0;
size_t max_size_;
bool override_write_;
bool block_read_;
};
#endif

Wyświetl plik

@ -0,0 +1,247 @@
#include <iostream>
#include <string>
#include <thread>
#include <complex>
#include <cmath>
#include <CaribouLite.hpp> // CPP API for CaribouLite
#include "circular_buffer.hpp" // for circular sample buffer
#define SAMPLE_RATE (4000000)
#define SAMPLE_RATE_CLOSEST (4194304)
#define MAX_FIFO_SECONDS (2)
#define MAX_FIFO_SIZE (SAMPLE_RATE_CLOSEST * MAX_FIFO_SECONDS)
#define TIME_BETWEEN_EPOCHS (5)
#define TIME_OF_SAMPLING (1)
#define RX_CHUNK_SAMPLES (8192)
// ==========================================================================================
// The Application context
// ==========================================================================================
typedef enum
{
app_state_setup = 0,
app_state_sampling = 1,
app_state_sleeping = 2,
} appState_en;
typedef struct
{
// device
CaribouLite* cl;
CaribouLiteRadio* radio;
// operational parameters
bool running;
float freq;
float gain;
size_t num_samples_read_so_far;
size_t epoch;
appState_en state;
bool requested_to_quit;
// buffers & threads
circular_buffer<std::complex<float>> *rx_fifo;
std::thread *dsp_thread;
} appContext_st;
static appContext_st app = {0};
// ==========================================================================================
// General printing and detection of the board
// ==========================================================================================
void printInfo(CaribouLite& cl)
{
std::cout << "Initialized CaribouLite: " << cl.IsInitialized() << std::endl;
std::cout << "API Versions: " << cl.GetApiVersion() << std::endl;
std::cout << "Hardware Serial Number: " << std::hex << cl.GetHwSerialNumber() << std::endl;
std::cout << "System Type: " << cl.GetSystemVersionStr() << std::endl;
std::cout << "Hardware Unique ID: " << cl.GetHwGuid() << std::endl;
}
// Detect boards
void detectBoard()
{
CaribouLite::SysVersion ver;
std::string name;
std::string guid;
if (CaribouLite::DetectBoard(&ver, name, guid))
{
std::cout << "Detected Version: " << CaribouLite::GetSystemVersionStr(ver) << ", Name: " << name << ", GUID: " << guid << std::endl;
}
else
{
std::cout << "Undetected CaribouLite!" << std::endl;
}
}
// Print radio information
void printRadioInformation(CaribouLiteRadio* radio)
{
std::cout << "Radio Name: " << radio->GetRadioName() << " MtuSize: " << std::dec << radio->GetNativeMtuSample() << " Samples" << std::endl;
std::vector<CaribouLiteFreqRange> range = radio->GetFrequencyRange();
std::cout << "Frequency Regions:" << std::endl;
for (int i = 0; i < range.size(); i++)
{
std::cout << " " << i << ": " << range[i] << std::endl;
}
}
// ==========================================================================================
// DSP Thread - The thread that processes data whenever it is available and its
// helper sub-functions
// ==========================================================================================
// Helper DSP function example: calculate the RSSI
float RSSI(const std::complex<float>* signal, size_t num_of_samples)
{
if (num_of_samples == 0)
{
return 0.0f;
}
float sum_of_squares = 0.0f;
for (size_t i = 0; i < num_of_samples && i < num_of_samples; ++i)
{
float vrms = std::norm(signal[i]);
sum_of_squares += vrms * vrms / 100.0;
}
float mean_of_squares = sum_of_squares / num_of_samples;
// Convert RMS value to dBm
return 10 * log10(mean_of_squares);
}
// Consumer (parallel DSP) thread
void dataConsumerThread(appContext_st* app)
{
std::cout << "Data consumer thread started" << std::endl;
std::complex<float> local_dsp_buffer[RX_CHUNK_SAMPLES * 4];
while (app->running)
{
// get the number of elements in the fifo
size_t num_lements = app->rx_fifo->size();
if (num_lements == 0)
{
std::this_thread::sleep_for(std::chrono::milliseconds(50));
continue;
}
size_t actual_read = app->rx_fifo->get(local_dsp_buffer, (num_lements>(RX_CHUNK_SAMPLES*4)) ? (RX_CHUNK_SAMPLES * 4) : num_lements);
if (actual_read)
{
// here goes the DSP
app->num_samples_read_so_far += actual_read;
float rssi = RSSI(local_dsp_buffer, actual_read);
printf("DSP EPOCH: %ld, NUM_READ: %ld, RSSI: %.3f\n", app->epoch, app->num_samples_read_so_far, rssi);
}
}
std::cout << "Data consumer thread exitting" << std::endl;
}
// ==========================================================================================
// Asynchronous API for receiving data and managing data flow in RX
// ==========================================================================================
// Rx Callback (async)
void receivedSamples(CaribouLiteRadio* radio, const std::complex<float>* samples, CaribouLiteMeta* sync, size_t num_samples)
{
for (int i = 0; i < 6; i ++)
{
std::cout << "[" << samples[i].real() << ", " << samples[i].imag() << "]";
}
std::cout << std::endl;
// push the received samples in the fifo
app.rx_fifo->put(samples, num_samples);
}
// ==========================================================================================
// A simple asynchronous DSP flow
// ==========================================================================================
int main ()
{
// try detecting the board before getting the instance
detectBoard();
CaribouLite &cl = CaribouLite::GetInstance();
printInfo(cl);
// get the radios
CaribouLiteRadio *s1g = cl.GetRadioChannel(CaribouLiteRadio::RadioType::S1G);
printRadioInformation(s1g);
// create the application context
app.cl = &cl;
app.radio = s1g;
app.freq = 900000000;
app.gain = 69;
app.rx_fifo = new circular_buffer<std::complex<float>>(MAX_FIFO_SIZE);
app.num_samples_read_so_far = 0;
app.state = app_state_sampling;
app.epoch = 0;
app.requested_to_quit = false;
app.running = true;
app.dsp_thread = new std::thread(dataConsumerThread, &app);
// time management
while (1)
{
switch(app.state)
{
//----------------------------------------------
case app_state_setup:
std::cout << "Starting Epoch " << app.epoch << std::endl;
// an example periodic radio setup stage
app.radio->SetRxGain(app.gain);
app.radio->SetFrequency(app.freq);
app.num_samples_read_so_far = 0;
// and now go directly to the next sampling stage
app.state = app_state_sampling;
break;
//----------------------------------------------
case app_state_sampling:
// start receiving
app.radio->StartReceiving(receivedSamples, RX_CHUNK_SAMPLES);
std::this_thread::sleep_for(std::chrono::milliseconds(TIME_OF_SAMPLING * 1000));
// stop receiving
app.radio->StopReceiving();
app.state = app_state_sleeping;
break;
//----------------------------------------------
case app_state_sleeping:
std::this_thread::sleep_for(std::chrono::milliseconds(TIME_BETWEEN_EPOCHS * 1000));
app.epoch ++;
// reset the fifo
app.rx_fifo->reset();
// either go the next epoch or quit the program
// this is an example flow but other possibilities exist
if (!app.requested_to_quit) app.state = app_state_setup;
else break;
break;
//----------------------------------------------
default:
break;
}
}
// cleanup - done by the creator
app.running = false;
app.dsp_thread->join();
delete app.dsp_thread;
delete app.rx_fifo;
return 0;
}

Wyświetl plik

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.2)
project(test_app)
# Find the package using pkg-config
find_package(PkgConfig REQUIRED)
pkg_check_modules(CARIBOULITE REQUIRED cariboulite)
# Add the executable
add_executable(test_app main.cpp)
# Include directories from the cariboulite package
target_include_directories(test_app PRIVATE ${CARIBOULITE_INCLUDE_DIRS})
# Link against the cariboulite library
target_link_libraries(test_app PRIVATE ${CARIBOULITE_LIBRARIES} -lcariboulite)

Wyświetl plik

@ -0,0 +1,150 @@
#include <iostream>
#include <string>
#include <CaribouLite.hpp>
#include <thread>
#include <complex>
#include <unistd.h>
#include <cmath>
// Print Board Information
void printInfo(CaribouLite& cl)
{
std::cout << "Initialized CaribouLite: " << cl.IsInitialized() << std::endl;
std::cout << "API Versions: " << cl.GetApiVersion() << std::endl;
std::cout << "Hardware Serial Number: " << std::hex << cl.GetHwSerialNumber() << std::endl;
std::cout << "System Type: " << cl.GetSystemVersionStr() << std::endl;
std::cout << "Hardware Unique ID: " << cl.GetHwGuid() << std::endl;
}
// Detect the board before instantiating it
void detectBoard()
{
CaribouLite::SysVersion ver;
std::string name;
std::string guid;
if (CaribouLite::DetectBoard(&ver, name, guid))
{
std::cout << "Detected Version: " << CaribouLite::GetSystemVersionStr(ver) << ", Name: " << name << ", GUID: " << guid << std::endl;
}
else
{
std::cout << "Undetected CaribouLite!" << std::endl;
}
}
// Calculate the RSSI
float RSSI(const std::complex<float>* signal, size_t num_of_samples)
{
if (num_of_samples == 0)
{
return 0.0f;
}
float sum_of_squares = 0.0f;
for (size_t i = 0; i < num_of_samples; ++i)
{
float vrmsp2 = (signal[i].real() * signal[i].real()) + (signal[i].imag() * signal[i].imag());
sum_of_squares += vrmsp2 / 100.0;
}
float mean_of_squares = sum_of_squares / num_of_samples;
// Convert RMS value to dBm
return 10 * log10(mean_of_squares);
}
// Rx Callback (async)
void receivedSamples(CaribouLiteRadio* radio, const std::complex<float>* samples, CaribouLiteMeta* sync, size_t num_samples)
{
std::cout << "Radio: " << radio->GetRadioName() << " Received " << std::dec << num_samples << " samples"
<< "RSSI: " << RSSI(samples, num_samples) << " dBm" << std::endl;
}
// Main entry
int main ()
{
std::complex<float>* samples = new std::complex<float>[128*1024];
// try detecting the board before getting the instance
detectBoard();
// get driver instance - use "CaribouLite&" rather than "CaribouLite" (ref)
// get a "synchronous" api instance
CaribouLite &cl = CaribouLite::GetInstance(false);
// print the info after connecting
printInfo(cl);
// get the radios
CaribouLiteRadio *s1g = cl.GetRadioChannel(CaribouLiteRadio::RadioType::S1G);
CaribouLiteRadio *hif = cl.GetRadioChannel(CaribouLiteRadio::RadioType::HiF);
// write radio information
std::cout << "First Radio Name: " << s1g->GetRadioName() << " MtuSize: " << std::dec << s1g->GetNativeMtuSample() << " Samples" << std::endl;
std::cout << "First Radio Name: " << hif->GetRadioName() << " MtuSize: " << std::dec << hif->GetNativeMtuSample() << " Samples" << std::endl;
std::vector<CaribouLiteFreqRange> range_s1g = s1g->GetFrequencyRange();
std::vector<CaribouLiteFreqRange> range_hif = hif->GetFrequencyRange();
std::cout << "S1G Frequency Regions:" << std::endl;
for (int i = 0; i < range_s1g.size(); i++)
{
std::cout << " " << i << ": " << range_s1g[i] << std::endl;
}
std::cout << "HiF Frequency Regions:" << std::endl;
for (int i = 0; i < range_hif.size(); i++)
{
std::cout << " " << i << ": " << range_hif[i] << std::endl;
}
// Receive Synchrnonously
try
{
hif->SetFrequency(2490000000);
}
catch (...)
{
std::cout << "The specified freq couldn't be used" << std::endl;
}
hif->SetRxGain(69);
hif->SetAgc(false);
hif->SetRxSampleRate(4000000);
//hif->StartReceiving();
s1g->SetRxGain(69);
s1g->SetAgc(false);
s1g->SetRxSampleRate(2000000);
s1g->StartReceiving();
int num_buffers = 10;
while (num_buffers--)
{
//s1g->FlushBuffers();
int ret = s1g->ReadSamples(samples, (1<<16));
if (ret > 0)
{
std::cout << "Radio: " << hif->GetRadioName() << " Received " << std::dec << ret << " samples"
<< "RSSI: " << RSSI(samples, ret) << " dBm" << std::endl;
}
}
/*try
{
s1g->SetFrequency(900100000);
}
catch (...)
{
std::cout << "The specified freq couldn't be used" << std::endl;
}
s1g->SetRxGain(69);
s1g->SetRxBandwidth(2500e3);
s1g->SetAgc(false);
s1g->StartReceiving(receivedSamples);*/
delete []samples;
return 0;
}

Wyświetl plik

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.2)
project(test_app)
# Find the package using pkg-config
find_package(PkgConfig REQUIRED)
pkg_check_modules(CARIBOULITE REQUIRED cariboulite)
# Add the executable
add_executable(test_app main.cpp)
# Include directories from the cariboulite package
target_include_directories(test_app PRIVATE ${CARIBOULITE_INCLUDE_DIRS})
# Link against the cariboulite library
target_link_libraries(test_app PRIVATE ${CARIBOULITE_LIBRARIES} -lcariboulite)

Wyświetl plik

@ -0,0 +1,141 @@
#include <iostream>
#include <string>
#include <CaribouLite.hpp>
#include <thread>
#include <complex>
#include <cmath>
// Print Board Information
void printInfo(CaribouLite& cl)
{
std::cout << "Initialized CaribouLite: " << cl.IsInitialized() << std::endl;
std::cout << "API Versions: " << cl.GetApiVersion() << std::endl;
std::cout << "Hardware Serial Number: " << std::hex << cl.GetHwSerialNumber() << std::endl;
std::cout << "System Type: " << cl.GetSystemVersionStr() << std::endl;
std::cout << "Hardware Unique ID: " << cl.GetHwGuid() << std::endl;
}
// Detect the board before instantiating it
void detectBoard()
{
CaribouLite::SysVersion ver;
std::string name;
std::string guid;
if (CaribouLite::DetectBoard(&ver, name, guid))
{
std::cout << "Detected Version: " << CaribouLite::GetSystemVersionStr(ver) << ", Name: " << name << ", GUID: " << guid << std::endl;
}
else
{
std::cout << "Undetected CaribouLite!" << std::endl;
}
}
// Rx Callback (async)
void receivedSamples(CaribouLiteRadio* radio, const std::complex<float>* samples, CaribouLiteMeta* sync, size_t num_samples)
{
std::cout << "Radio: " << radio->GetRadioName() << " Received " << std::dec << num_samples << " samples" << std::endl;
}
// Tx buffer generation
void generateCwWave(float freq, float sample_rate, std::complex<float>* samples, size_t num_samples)
{
// angular frequency
float omega = 2.0f * M_PI * freq;
for (int i = 0; i < num_samples; ++i)
{
float t = (float)(i) / sample_rate;
float I = cos(omega * t);
float Q = sin(omega * t);
samples[i] = std::complex<float>(I, Q);
}
}
// Main entry
int main ()
{
// try detecting the board before getting the instance
detectBoard();
// get driver instance - use "CaribouLite&" rather than "CaribouLite" (ref)
CaribouLite &cl = CaribouLite::GetInstance();
// print the info after connecting
printInfo(cl);
// get the radios
CaribouLiteRadio *s1g = cl.GetRadioChannel(CaribouLiteRadio::RadioType::S1G);
CaribouLiteRadio *hif = cl.GetRadioChannel(CaribouLiteRadio::RadioType::HiF);
// write radio information
std::cout << "First Radio Name: " << s1g->GetRadioName() << " MtuSize: " << std::dec << s1g->GetNativeMtuSample() << " Samples" << std::endl;
std::cout << "First Radio Name: " << hif->GetRadioName() << " MtuSize: " << std::dec << hif->GetNativeMtuSample() << " Samples" << std::endl;
std::vector<CaribouLiteFreqRange> range_s1g = s1g->GetFrequencyRange();
std::vector<CaribouLiteFreqRange> range_hif = hif->GetFrequencyRange();
std::cout << "S1G Frequency Regions:" << std::endl;
for (int i = 0; i < range_s1g.size(); i++)
{
std::cout << " " << i << ": " << range_s1g[i] << std::endl;
}
std::cout << "HiF Frequency Regions:" << std::endl;
for (int i = 0; i < range_hif.size(); i++)
{
std::cout << " " << i << ": " << range_hif[i] << std::endl;
}
/********************************************************************************/
/* TRANSMITTING CW */
/********************************************************************************/
/*try
{
s1g->SetFrequency(900000000);
}
catch (...)
{
std::cout << "The specified freq couldn't be used" << std::endl;
}
s1g->SetTxPower(0);
s1g->SetTxBandwidth(1e6);
s1g->SetTxSampleRate(4e6);
s1g->StartTransmittingCw();
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
s1g->StopTransmitting();*/
/********************************************************************************/
/* TRANSMITTING */
/********************************************************************************/
std::complex<float>* samples = new std::complex<float>[s1g->GetNativeMtuSample()];
generateCwWave(500e3, 4e6, samples, s1g->GetNativeMtuSample());
try
{
s1g->SetFrequency(900000000);
}
catch (...)
{
std::cout << "The specified freq couldn't be used" << std::endl;
}
s1g->SetTxPower(0);
s1g->SetTxBandwidth(1e6);
s1g->SetTxSampleRate(4e6);
s1g->StartTransmitting();
for (int i = 0; i < 18; i++)
{
printf("buffer #%d\n", i);
s1g->WriteSamples(samples, s1g->GetNativeMtuSample());
}
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
s1g->StopTransmitting();
delete [] samples;
return 0;
}

Wyświetl plik

@ -20,7 +20,7 @@ void detectBoard()
CaribouLite::SysVersion ver;
std::string name;
std::string guid;
if (CaribouLite::DetectBoard(&ver, name, guid))
{
std::cout << "Detected Version: " << CaribouLite::GetSystemVersionStr(ver) << ", Name: " << name << ", GUID: " << guid << std::endl;
@ -28,14 +28,13 @@ void detectBoard()
else
{
std::cout << "Undetected CaribouLite!" << std::endl;
}
}
}
// Rx Callback (async)
void receivedSamples(CaribouLiteRadio* radio, const std::complex<float>* samples, CaribouLiteMeta* sync, size_t num_samples)
{
std::cout << "Radio: " << radio->GetRadioName() << " Received " << std::dec << num_samples << " samples" << std::endl;
}
@ -44,21 +43,21 @@ int main ()
{
// try detecting the board before getting the instance
detectBoard();
// get driver instance - use "CaribouLite&" rather than "CaribouLite" (ref)
CaribouLite &cl = CaribouLite::GetInstance();
// print the info after connecting
printInfo(cl);
// get the radios
CaribouLiteRadio *s1g = cl.GetRadioChannel(CaribouLiteRadio::RadioType::S1G);
CaribouLiteRadio *hif = cl.GetRadioChannel(CaribouLiteRadio::RadioType::HiF);
// write radio information
std::cout << "First Radio Name: " << s1g->GetRadioName() << " MtuSize: " << std::dec << s1g->GetNativeMtuSample() << " Samples" << std::endl;
std::cout << "First Radio Name: " << hif->GetRadioName() << " MtuSize: " << std::dec << hif->GetNativeMtuSample() << " Samples" << std::endl;
// start receiving until enter pressed on 900MHz
s1g->SetFrequency(900000000);
s1g->SetRxGain(50);
@ -66,11 +65,11 @@ int main ()
s1g->StartReceiving(receivedSamples);
getchar();
hif->SetFrequency(900000000);
hif->StartReceiving(receivedSamples, 20000);
getchar();
return 0;
}

Wyświetl plik

@ -5,7 +5,7 @@ pcf_file = ./io.pcf
top.bin:
yosys -p 'synth_ice40 -top top -json $(filename).json -blif $(filename).blif' -p 'ice40_opt' -p 'fsm_opt' $(filename).v
#nextpnr-ice40 --lp1k --package qn84 --json $(filename).json --pcf $(pcf_file) --asc $(filename).asc
nextpnr-ice40 --lp1k --package qn84 --json $(filename).json --pcf $(pcf_file) --asc $(filename).asc --freq 64 --parallel-refine --opt-timing --timing-allow-fail
nextpnr-ice40 --lp1k --package qn84 --json $(filename).json --pcf $(pcf_file) --asc $(filename).asc --freq 80 --parallel-refine --opt-timing --seed 5 --timing-allow-fail
#nextpnr-ice40 --json blinky.json --pcf blinky.pcf --asc blinky.asc --gui
icepack $(filename).asc $(filename).bin

Wyświetl plik

@ -15,7 +15,7 @@ module io_ctrl
input [3:0] i_config,
output o_led0,
output o_led1,
output [7:0] o_pmod,
output [3:0] o_pmod,
// Analog interfaces
output o_mixer_fm,
@ -26,7 +26,7 @@ module io_ctrl
output o_tr_vc2,
output o_shdn_tx_lna,
output o_shdn_rx_lna,
output o_mixer_en
output o_mixer_en
);
@ -73,7 +73,7 @@ module io_ctrl
reg led0_state;
reg led1_state;
reg [7:0] pmod_dir_state;
reg [7:0] pmod_state;
reg [3:0] pmod_state;
reg [7:0] rf_pin_state;
reg mixer_en_state;
@ -146,7 +146,8 @@ module io_ctrl
//----------------------------------------------
ioc_pmod_val: begin
o_data_out <= pmod_state;
o_data_out[3:0] <= pmod_state;
o_data_out[7:4] <= 4'b0000;
end
//----------------------------------------------
@ -191,7 +192,7 @@ module io_ctrl
//----------------------------------------------
ioc_pmod_val: begin
pmod_state <= i_data_in;
pmod_state[3:0] <= i_data_in[3:0];
end
//----------------------------------------------

Wyświetl plik

@ -1,15 +1,15 @@
module lvds_tx (
input i_rst_b,
input i_ddr_clk,
input i_rst_b,
input i_ddr_clk,
output reg[1:0] o_ddr_data,
input i_fifo_empty,
output o_fifo_read_clk,
input i_fifo_empty,
output o_fifo_read_clk,
output o_fifo_pull,
input [31:0] i_fifo_data,
input [31:0] i_fifo_data,
input [3:0] i_sample_gap,
input i_tx_state,
input i_sync_input,
input i_tx_state,
input i_sync_input,
input i_debug_lb,
output o_tx_state_bit,
output o_sync_state_bit,
@ -17,28 +17,29 @@ module lvds_tx (
// STATES and PARAMS
localparam
tx_state_sync = 1'b0,
tx_state_tx = 1'b1;
tx_state_sync = 1'b0,
tx_state_tx = 1'b1;
localparam sync_duration_frames = 4'd10; // at least 2.5usec
localparam zero_frame = 32'b00000000_00000000_00000000_00000000;
localparam lb_frame = 32'b10000100_00000011_01110000_01001000;
// Internal Registers
// Internal Registers
reg [3:0] r_sync_count;
wire frame_pull_clock;
wire frame_assign_clock;
reg r_state;
reg [3:0] r_phase_count;
reg [31:0] r_fifo_data;
reg [31:0] r_fifo_data;
reg r_pulled;
reg r_schedule_zero_frame;
// Initial conditions
initial begin
// Initial conditions
initial begin
r_phase_count = 4'd15;
r_fifo_data <= zero_frame;
end
end
assign o_fifo_read_clk = i_ddr_clk;
assign o_fifo_read_clk = i_ddr_clk;
assign o_tx_state_bit = r_state;
assign o_sync_state_bit = 1'b0;
assign o_fifo_pull = r_pulled;
@ -52,15 +53,17 @@ module lvds_tx (
r_phase_count <= r_phase_count - 1;
end
end
// SYNC AND MANAGEMENT
always @(posedge i_ddr_clk) begin
if (i_rst_b == 1'b0) begin
always @(posedge i_ddr_clk)
begin
if (i_rst_b == 1'b0) begin
r_state <= tx_state_sync;
r_pulled <= 1'b0;
r_fifo_data <= zero_frame;
r_sync_count <= sync_duration_frames;
r_schedule_zero_frame <= 1'b0;
end else begin
end else begin
case (r_state)
//----------------------------------------------
tx_state_sync:
@ -83,14 +86,15 @@ module lvds_tx (
r_state <= tx_state_sync;
r_fifo_data <= zero_frame;
end
end else begin
end else begin
r_sync_count <= r_sync_count - 1;
r_schedule_zero_frame <= 1'b1;
//r_fifo_data <= zero_frame;
r_state <= tx_state_sync;
end
end
end
end
//----------------------------------------------
tx_state_tx:
begin
@ -106,7 +110,7 @@ module lvds_tx (
r_sync_count <= sync_duration_frames;
r_fifo_data <= zero_frame;
r_state <= tx_state_sync;
end else begin
end else begin
r_fifo_data <= i_fifo_data;
if (i_sample_gap > 0) begin
r_sync_count <= i_sample_gap;
@ -115,11 +119,11 @@ module lvds_tx (
r_state <= tx_state_tx;
end
end
r_pulled <= 1'b0;
end
end
end
endcase
end
end
end
endmodule

Wyświetl plik

@ -29,7 +29,7 @@ module smi_ctrl
output o_smi_write_req,
input i_smi_test,
output o_channel,
output o_dir,
output o_dir,
// TX CONDITIONAL
output reg o_cond_tx,
@ -171,7 +171,7 @@ module smi_ctrl
tx_state_third = 2'b10,
tx_state_fourth = 2'b11;
reg [4:0] int_cnt_tx;
reg [12:0] int_cnt_tx;
reg [31:0] r_fifo_pushed_data;
reg [1:0] tx_reg_state;
reg modem_tx_ctrl;
@ -194,7 +194,11 @@ module smi_ctrl
r_fifo_pushed_data <= 32'h00000000;
modem_tx_ctrl <= 1'b0;
cond_tx_ctrl <= 1'b0;
//cnt <= 0;
// DEBUG
int_cnt_tx <= 0;
// END_DEBUG
end else begin
case (tx_reg_state)
//----------------------------------------------
@ -247,10 +251,11 @@ module smi_ctrl
begin
if (i_smi_data_in[7] == 1'b0) begin
o_tx_fifo_pushed_data <= {r_fifo_pushed_data[31:8], i_smi_data_in[6:0], 1'b0};
//o_tx_fifo_pushed_data <= {i_smi_data_in[6:0], 1'b0, r_fifo_pushed_data[15:8], r_fifo_pushed_data[23:16], r_fifo_pushed_data[31:24]};
//o_tx_fifo_pushed_data <= {2'b10, cnt, 1'b1, 2'b01, 13'h3F, 1'b0};
//o_tx_fifo_pushed_data <= {cnt, cnt, 6'b111111};
//cnt <= cnt + 1024;
o_tx_fifo_pushed_data <= {2'b10, int_cnt_tx, 1'b1, 2'b01, 13'h3F, 1'b0};
int_cnt_tx <= int_cnt_tx + 512;
w_fifo_push_trigger <= 1'b1;
o_cond_tx <= cond_tx_ctrl;
end else begin

Wyświetl plik

@ -16,6 +16,16 @@ module sys_ctrl
output o_debug_smi_test,
output o_debug_loopback_tx,
output [3:0] o_tx_sample_gap,
output o_rx_sync_type09,
output o_rx_sync_type24,
output o_tx_sync_type09,
output o_tx_sync_type24,
output o_rx_sync_09,
output o_rx_sync_24,
output o_tx_sync_09,
output o_tx_sync_24,
);
// MODULE SPECIFIC IOC LIST
@ -26,7 +36,8 @@ module sys_ctrl
ioc_manu_id = 5'b00010, // read only
ioc_error_state = 5'b00011, // read only
ioc_debug_modes = 5'b00101, // write only
ioc_tx_sample_gap = 5'b00110; // read / write
ioc_tx_sample_gap = 5'b00110, // read / write
ioc_soft_sync = 5'b00111; // write only
// MODULE SPECIFIC PARAMS
// ----------------------
@ -40,12 +51,32 @@ module sys_ctrl
reg debug_fifo_push;
reg debug_fifo_pull;
reg debug_smi_test;
reg debug_loopback_tx;
reg [3:0] tx_sample_gap;
reg debug_loopback_tx;
reg [3:0] tx_sample_gap;
reg rx_sync_type09;
reg rx_sync_type24;
reg tx_sync_type09;
reg tx_sync_type24;
reg rx_sync_09;
reg rx_sync_24;
reg tx_sync_09;
reg tx_sync_24;
assign o_debug_fifo_push = debug_fifo_push;
assign o_debug_fifo_pull = debug_fifo_pull;
assign o_debug_smi_test = debug_smi_test;
assign o_rx_sync_type09 = rx_sync_type09;
assign o_tx_sync_type09 = tx_sync_type09;
assign o_rx_sync_type24 = rx_sync_type24;
assign o_tx_sync_type24 = tx_sync_type24;
assign o_rx_sync_09 = rx_sync_09;
assign o_tx_sync_09 = tx_sync_09;
assign o_rx_sync_24 = rx_sync_24;
assign o_tx_sync_24 = tx_sync_24;
// MODULE MAIN PROCESS
// -------------------
@ -58,6 +89,17 @@ module sys_ctrl
debug_smi_test <= 1'b0;
debug_loopback_tx <= 1'b0;
tx_sample_gap <= 4'd0;
rx_sync_type09 <= 1'b0;
rx_sync_type24 <= 1'b0;
tx_sync_type09 <= 1'b0;
tx_sync_type24 <= 1'b0;
rx_sync_09 <= 1'b0;
tx_sync_09 <= 1'b0;
rx_sync_24 <= 1'b0;
tx_sync_24 <= 1'b0;
end else if (i_cs == 1'b1) begin
//=============================================
// READ OPERATIONS
@ -70,7 +112,10 @@ module sys_ctrl
//----------------------------------------------
ioc_tx_sample_gap: begin
o_data_out[3:0] <= tx_sample_gap;
o_data_out[7:4] <= 4'd0;
o_data_out[4] <= rx_sync_type09;
o_data_out[5] <= rx_sync_type24;
o_data_out[6] <= tx_sync_type09;
o_data_out[7] <= tx_sync_type24;
end
endcase
end
@ -89,6 +134,17 @@ module sys_ctrl
//----------------------------------------------
ioc_tx_sample_gap: begin
tx_sample_gap <= i_data_in[3:0];
rx_sync_type09 <= i_data_in[4];
rx_sync_type24 <= i_data_in[5];
tx_sync_type09 <= i_data_in[6];
tx_sync_type24 <= i_data_in[7];
end
//----------------------------------------------
ioc_soft_sync: begin
rx_sync_09 <= i_data_in[0];
tx_sync_09 <= i_data_in[1];
rx_sync_24 <= i_data_in[2];
tx_sync_24 <= i_data_in[3];
end
endcase
end

Plik diff jest za duży Load Diff

Plik binarny nie jest wyświetlany.

Plik diff jest za duży Load Diff

Plik diff jest za duży Load Diff

Wyświetl plik

@ -50,27 +50,28 @@ module top (
//
// RPI PIN | FPGA TOP-LEVEL SIGNAL
// ------------------------------------------------------------------------
// GPIO2_SA3 | i_smi_a[2] - RX09 / RX24 channel select
// GPIO3_SA2 | i_smi_a[1] - Tx SMI (0) / Rx SMI (1) select
// GPIO4_SA1 | i_smi_a[0] - used as a sys async reset (GBIN1)
// GPIO2_SA3 | i_smi_a3 - RX09 / RX24 channel select
// GPIO3_SA2 | i_smi_a2 - Tx SMI (0) / Rx SMI (1) select
// GPIO4_SA1 | i_rst_b - used as a sys async reset (GBIN1)
// GPIO5_SA0 | Not connected to FPGA (MixerRst)
//
// In order to perform SMI data bus direction selection (highZ / PushPull)
// signal a[0] was chosen, while the '0' level (default) denotes RPI => FPGA
// direction, and the DATA bus is highZ (recessive mode).
// The signal a[2] selects the RX source (900 MHZ or 2.4GHz)
// The signal a[1] can be used in the future for other purposes
// The signal i_smi_a2 selects Tx(0) or Rx(1) direction
// The signal i_smi_a3 selects the RX source (900 MHZ or 2.4GHz)
//
// Description | a[2] (SA3)| a[1] (SA2) |
// -------------|------------|---------------|
// | 0 | 0 |
// TX |------------| RPI => FPGA |
// | 1 | Data HighZ |
// -------------|------------|---------------|
// RX09 | 0 | 1 |
// -------------|------------| FPGA => RPI |
// RX24 | 1 | Data PushPull |
// -------------|------------|---------------|
// Description | a2 (SA2) | a3 (SA3) |
// -------------|---------------|------------|
// | 0 | 0 |
// TX | RPI => FPGA |------------|
// | Data HighZ | 1 |
// -------------|---------------|------------|
// RX09 | 1 | 0 |
// -------------| FPGA => RPI |------------|
// RX24 | Data PushPull | 1 |
// -------------|---------------|------------|
input i_smi_a2,
input i_smi_a3,
@ -105,6 +106,26 @@ module top (
wire [7:0] w_tx_data_io;
wire [7:0] w_tx_data_smi;
wire w_rx_sync_type_09;
wire w_rx_sync_type_24;
wire w_tx_sync_type_09;
wire w_tx_sync_type_24;
wire w_rx_sync_09;
wire w_rx_sync_24;
wire w_tx_sync_09;
wire w_tx_sync_24;
wire w_rx_sync_input_09;
wire w_rx_sync_input_24;
wire w_tx_sync_input_09;
wire w_tx_sync_input_24;
assign w_rx_sync_input_09 = (w_rx_sync_type_09) ? io_pmod[7] : w_rx_sync_09;
assign w_rx_sync_input_24 = (w_rx_sync_type_24) ? io_pmod[6] : w_rx_sync_24;
assign w_tx_sync_input_09 = (w_tx_sync_type_09) ? io_pmod[5] : w_tx_sync_09;
assign w_tx_sync_input_24 = (w_tx_sync_type_24) ? io_pmod[4] : w_tx_sync_24;
//=========================================================================
// INSTANCES
//=========================================================================
@ -138,11 +159,22 @@ module top (
.i_cs(w_cs[0]),
.i_fetch_cmd(w_fetch),
.i_load_cmd(w_load),
.o_debug_fifo_push(),
.o_debug_fifo_pull(),
.o_debug_smi_test(),
.o_debug_loopback_tx(w_debug_lb_tx),
.o_tx_sample_gap(tx_sample_gap),
.o_rx_sync_type09(w_rx_sync_type_09),
.o_rx_sync_type24(w_rx_sync_type_24),
.o_tx_sync_type09(w_tx_sync_type_09),
.o_tx_sync_type24(w_tx_sync_type_24),
.o_rx_sync_09(w_rx_sync_09),
.o_rx_sync_24(w_rx_sync_24),
.o_tx_sync_09(w_tx_sync_09),
.o_tx_sync_24(w_tx_sync_24)
);
wire w_debug_fifo_push;
@ -165,9 +197,9 @@ module top (
// Digital interfaces
.i_button(i_button),
.i_config(i_config),
.o_led0 (/*o_led0*/),
.o_led1 (/*o_led1*/),
.o_pmod (),
.o_led0 (o_led0),
.o_led1 (o_led1),
.o_pmod (/*io_pmod[3:0]*/),
// Analog interfaces
.o_mixer_fm(/*o_mixer_fm*/),
@ -181,6 +213,11 @@ module top (
.o_mixer_en(/*o_mixer_en*/)
);
assign io_pmod[0] = ~lvds_clock_buf;
assign io_pmod[1] = w_lvds_tx_d0;
assign io_pmod[2] = w_lvds_tx_d1;
assign io_pmod[3] = i_smi_swe_srw;
//=========================================================================
// CONBINATORIAL ASSIGNMENTS
//=========================================================================
@ -266,31 +303,49 @@ module top (
// Non-inverting, P-side of pair
SB_IO #(
.PIN_TYPE (6'b010000), // {PIN_OUTPUT_DDR, PIN_INPUT_REGISTER }
.PIN_TYPE (6'b010000), // {PIN_OUTPUT_DDR, PIN_OUTPUT_REGISTER }
.IO_STANDARD("SB_LVCMOS"),
) iq_tx_p (
.PACKAGE_PIN(o_iq_tx_p),
.OUTPUT_CLK(lvds_clock_buf),
.OUTPUT_CLK(~lvds_clock_buf),
.D_OUT_0(~w_lvds_tx_d0),
.D_OUT_1(~w_lvds_tx_d1)
);
// Inverting, N-side of pair
SB_IO #(
.PIN_TYPE (6'b010000), // {PIN_OUTPUT_DDR, PIN_INPUT_REGISTER }
.PIN_TYPE (6'b010000), // {PIN_OUTPUT_DDR, PIN_OUTPUT_REGISTER }
.IO_STANDARD("SB_LVCMOS"),
) iq_tx_n (
.PACKAGE_PIN(o_iq_tx_n),
.OUTPUT_CLK(lvds_clock_buf),
.OUTPUT_CLK(~lvds_clock_buf),
.D_OUT_0(w_lvds_tx_d0),
.D_OUT_1(w_lvds_tx_d1)
);
// Non-inverting, P-side clock
SB_IO #(
.PIN_TYPE(6'b011001),
.IO_STANDARD("SB_LVCMOS")
) iq_tx_clk_p (
.PACKAGE_PIN(o_iq_tx_clk_p),
.D_OUT_0(lvds_clock_buf),
);
// Inverting, N-side clock
SB_IO #(
.PIN_TYPE(6'b011001),
.IO_STANDARD("SB_LVCMOS")
) iq_tx_clk_n (
.PACKAGE_PIN(o_iq_tx_clk_n),
.D_OUT_0(~lvds_clock_buf),
);
// Logic on a clock signal is very bad - try to use a dedicated
// SB_IO
assign o_iq_tx_clk_p = lvds_clock_buf;
assign o_iq_tx_clk_n = ~lvds_clock_buf;
//assign o_iq_tx_clk_p = lvds_clock_buf;
//assign o_iq_tx_clk_n = ~lvds_clock_buf;
//=========================================================================
// LVDS RX SIGNAL FROM MODEM
@ -318,7 +373,7 @@ module top (
.o_fifo_push(w_rx_09_fifo_push),
.o_fifo_data (w_rx_09_fifo_data),
.i_sync_input (1'b0),
.i_sync_input (w_rx_sync_input_09),
.o_debug_state()
);
@ -333,7 +388,7 @@ module top (
.o_fifo_push(w_rx_24_fifo_push),
.o_fifo_data (w_rx_24_fifo_data),
.i_sync_input (1'b0),
.i_sync_input (w_rx_sync_input_24),
.o_debug_state()
);
@ -344,9 +399,6 @@ module top (
wire [31:0] w_rx_fifo_pulled_data;
wire w_rx_fifo_full;
wire w_rx_fifo_empty;
wire channel;
assign channel = i_smi_a3;
complex_fifo #(
.ADDR_WIDTH(10), // 1024 samples
@ -382,12 +434,12 @@ module top (
.i_fifo_data(w_tx_fifo_pulled_data),
.i_sample_gap(tx_sample_gap),
.i_tx_state(~w_smi_data_direction),
.i_sync_input(1'b0),
.i_sync_input(w_tx_sync_input_09),
.i_debug_lb(w_debug_lb_tx),
.o_tx_state_bit(),
.o_sync_state_bit(),
);
wire w_tx_fifo_full;
wire w_tx_fifo_empty;
wire w_tx_fifo_read_clk;
@ -418,6 +470,11 @@ module top (
.debug_push(1'b0)
);
wire channel;
wire w_smi_data_direction;
//assign channel = i_smi_a3;
//assign w_smi_data_direction = i_smi_a2;
smi_ctrl smi_ctrl_ins (
.i_rst_b(i_rst_b),
.i_sys_clk(w_clock_sys),
@ -445,8 +502,8 @@ module top (
.i_smi_data_in(w_smi_data_input),
.o_smi_read_req(w_smi_read_req),
.o_smi_write_req(w_smi_write_req),
.o_channel(/*channel*/),
.o_dir (/*w_smi_data_direction*/),
.o_channel(channel),
.o_dir (w_smi_data_direction),
.i_smi_test(1'b0/*w_debug_smi_test*/),
.o_cond_tx(),
.o_address_error()
@ -456,7 +513,6 @@ module top (
wire [7:0] w_smi_data_input;
wire w_smi_read_req;
wire w_smi_write_req;
wire w_smi_data_direction;
// the "Writing" flag indicates that the data[7:0] direction (inout)
// from the FPGA's SMI module should be "output". This happens when the
@ -464,7 +520,6 @@ module top (
// The address has the MSB '1' when in RX mode. otherwise (when IDLE or TX)
// the data is high-z, which is the more "recessive" mode
assign w_smi_data_direction = i_smi_a2;
SB_IO #(
.PIN_TYPE(6'b1010_01),
.PULLUP (1'b0)
@ -538,12 +593,10 @@ module top (
.D_IN_0(w_smi_data_input[7])
);
// We need the 'o_smi_write_req' to be 1 only when the direction is TX
// (w_smi_data_direction == 0) and the write fifo is not full
assign o_smi_read_req = (w_smi_data_direction) ? w_smi_read_req : w_smi_write_req;
assign o_smi_write_req = 1'bZ;
assign o_led0 = w_smi_data_direction;
assign o_led1 = channel;
//assign o_led0 = w_smi_data_direction;
//assign o_led1 = channel;
endmodule // top

Wyświetl plik

@ -175,7 +175,7 @@ public:
void StartReceiving();
void StartReceivingInternal(size_t samples_per_chunk);
void StopReceiving(void);
void StartTransmitting(std::function<void(CaribouLiteRadio*, std::complex<float>*, const bool*, size_t*)> on_data_request, size_t samples_per_chunk);
void StartTransmitting(void);
void StartTransmittingLo(void);
void StartTransmittingCw(void);
void StopTransmitting(void);
@ -198,6 +198,7 @@ private:
const CaribouLite* _device;
const RadioType _type;
// Rx information
bool _rx_thread_running;
bool _rx_is_active;
std::thread *_rx_thread;
@ -209,14 +210,12 @@ private:
RxCbType _rxCallbackType;
ApiType _api_type;
bool _tx_thread_running;
// Tx information
bool _tx_is_active;
std::thread *_tx_thread;
std::function<void(CaribouLiteRadio*, std::complex<float>*, const bool*, size_t*)> _on_data_request;
size_t _tx_samples_per_chunk;
// buffers
cariboulite_sample_complex_int16 *_read_samples;
std::complex<short> *_write_samples;
cariboulite_sample_meta* _read_metadata;
private:

Wyświetl plik

@ -132,7 +132,32 @@ int CaribouLiteRadio::ReadSamples(std::complex<short>* samples, size_t num_to_re
//==================================================================
int CaribouLiteRadio::WriteSamples(std::complex<float>* samples, size_t num_to_write)
{
return 0;
// fill in the _write_samples internal buffer
size_t written_so_far = 0;
size_t left_to_write = num_to_write;
size_t mtu_size = GetNativeMtuSample();
while (written_so_far < num_to_write)
{
size_t current_write = left_to_write;
size_t k = written_so_far;
if (current_write > mtu_size) current_write = mtu_size;
for (size_t i = 0; i < current_write; i++, k++)
{
_write_samples[i].real((uint16_t)(samples[k].real() * 4096));
_write_samples[i].imag((uint16_t)(samples[k].imag() * 4096));
}
int ret = WriteSamples(_write_samples, current_write);
if (ret <= 0)
{
break;
}
written_so_far += ret;
left_to_write -= ret;
}
return written_so_far;
}
//==================================================================
@ -143,20 +168,6 @@ int CaribouLiteRadio::WriteSamples(std::complex<short>* samples, size_t num_to_w
num_to_write);
}
//==================================================================
void CaribouLiteRadio::CaribouLiteTxThread(CaribouLiteRadio* radio)
{
while (radio->_tx_thread_running)
{
if (!radio->_tx_is_active)
{
std::this_thread::sleep_for(std::chrono::milliseconds(4));
continue;
}
// TBD
}
}
//==================================================================
CaribouLiteRadio::CaribouLiteRadio( const cariboulite_radio_state_st* radio,
RadioType type,
@ -164,25 +175,26 @@ CaribouLiteRadio::CaribouLiteRadio( const cariboulite_radio_state_st* radio,
const CaribouLite* parent)
: _radio(radio), _device(parent), _type(type), _rxCallbackType(RxCbType::None), _api_type(api_type)
{
size_t mtu_size = GetNativeMtuSample();
if (_api_type == Async)
{
//printf("Creating Radio Type %d ASYNC\n", type);
_rx_thread_running = true;
_rx_thread = new std::thread(CaribouLiteRadio::CaribouLiteRxThread, this);
_tx_thread_running = true;
_tx_thread = new std::thread(CaribouLiteRadio::CaribouLiteTxThread, this);
}
else
{
//printf("Creating Radio Type %d SYNC\n", type);
_read_samples = NULL;
_read_metadata = NULL;
size_t mtu_size = GetNativeMtuSample();
// allocate internal buffers
_read_samples = new cariboulite_sample_complex_int16[mtu_size];
_read_samples = new cariboulite_sample_complex_int16[mtu_size];
_read_metadata = new cariboulite_sample_meta[mtu_size];
}
_write_samples = NULL;
_write_samples = new std::complex<short>[mtu_size];
}
//==================================================================
@ -197,18 +209,18 @@ CaribouLiteRadio::~CaribouLiteRadio()
_rx_thread_running = false;
_rx_thread->join();
if (_rx_thread) delete _rx_thread;
_tx_thread_running = false;
_tx_thread->join();
if (_tx_thread) delete _tx_thread;
}
else
{
if (_read_samples) delete [] _read_samples;
_read_samples = NULL;
if (_read_metadata) delete [] _read_metadata;
_read_metadata = NULL;
}
}
if (_write_samples) delete [] _write_samples;
_write_samples = NULL;
}
// Gain
@ -596,11 +608,9 @@ void CaribouLiteRadio::StopReceiving()
}
//==================================================================
void CaribouLiteRadio::StartTransmitting(std::function<void(CaribouLiteRadio*, std::complex<float>*, const bool*, size_t*)> on_data_request, size_t samples_per_chunk)
void CaribouLiteRadio::StartTransmitting()
{
_rx_is_active = false;
_on_data_request = on_data_request;
_tx_samples_per_chunk = samples_per_chunk;
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_rx, false);
cariboulite_radio_set_cw_outputs((cariboulite_radio_state_st*)_radio, false, false);
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_tx, true);

Wyświetl plik

@ -90,10 +90,6 @@ typedef enum
at86rf215_radio_rx_bw_BW1250KHZ_IF2000KHZ = 0x9, // at86rf215_radio_rx_f_cut_0_75_half_fs
at86rf215_radio_rx_bw_BW1600KHZ_IF2000KHZ = 0xA, // at86rf215_radio_rx_f_cut_half_fs
at86rf215_radio_rx_bw_BW2000KHZ_IF2000KHZ = 0xB, // at86rf215_radio_rx_f_cut_half_fs
at86rf215_radio_rx_bw_BW2000KHZ_IFCCKHZ = 0xC, // **
at86rf215_radio_rx_bw_BW2000KHZ_IFDDHZ = 0xD, // **
at86rf215_radio_rx_bw_BW2000KHZ_IFEEKHZ = 0xE, // **
at86rf215_radio_rx_bw_BW2000KHZ_IFFFKHZ = 0xF, // **
} at86rf215_radio_rx_bw_en;
typedef enum

Wyświetl plik

@ -13,13 +13,14 @@
//--------------------------------------------------------------
// Static Definitions
//--------------------------------------------------------------
#define IOC_MOD_VER 0
#define IOC_SYS_CTRL_SYS_VERSION 1
#define IOC_SYS_CTRL_MANU_ID 2
#define IOC_SYS_CTRL_SYS_ERR_STAT 3
#define IOC_SYS_CTRL_SYS_SOFT_RST 4
#define IOC_SYS_CTRL_DEBUG_MODES 5
#define IOC_SYS_CTRL_SYS_TX_SAMPLE_GAP 6
#define IOC_MOD_VER 0
#define IOC_SYS_CTRL_SYS_VERSION 1
#define IOC_SYS_CTRL_MANU_ID 2
#define IOC_SYS_CTRL_SYS_ERR_STAT 3
#define IOC_SYS_CTRL_SYS_SOFT_RST 4
#define IOC_SYS_CTRL_DEBUG_MODES 5
#define IOC_SYS_CTRL_TX_SAMPLE_GAP 6
#define IOC_SYS_CTRL_SOFT_SYNC 7
#define IOC_IO_CTRL_MODE 1
#define IOC_IO_CTRL_DIG_PIN 2
@ -31,7 +32,7 @@
#define IOC_SMI_CTRL_FIFO_STATUS 1
#define IOC_SMI_CHANNEL_SELECT 2
#define IOC_SMI_CTRL_DIR_SELECT 3
#define IOC_SMI_CTRL_DIR_SELECT 3
//--------------------------------------------------------------
// Internal Data-Types
@ -380,21 +381,42 @@ int caribou_fpga_get_errors (caribou_fpga_st* dev, uint8_t *err_map)
.ioc = IOC_SYS_CTRL_SYS_ERR_STAT
};
*err_map = 0;
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), err_map);
if (err_map)
{
*err_map = 0;
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), err_map);
}
return -1;
}
//--------------------------------------------------------------
int caribou_fpga_set_sys_ctrl_tx_sample_gap (caribou_fpga_st* dev, uint8_t gap)
{
uint8_t actual_val = 0;
uint8_t actual_gap = 0;
CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_sys_ctrl_tx_sample_gap");
// read before write
caribou_fpga_opcode_st oc =
{
.rw = caribou_fpga_rw_write,
.rw = caribou_fpga_rw_read,
.mid = caribou_fpga_mid_sys_ctrl,
.ioc = IOC_SYS_CTRL_SYS_TX_SAMPLE_GAP,
.ioc = IOC_SYS_CTRL_TX_SAMPLE_GAP,
};
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &gap);
int ret = caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &actual_val);
if (ret != 0) return -1;
actual_gap = actual_val & 0xF;
actual_val &= 0xF0;
if (gap != actual_gap)
{
// only if change is needed
oc.rw = caribou_fpga_rw_write;
actual_val |= (gap & 0xF);
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &actual_val);
}
return 0;
}
//--------------------------------------------------------------
@ -406,14 +428,104 @@ int caribou_fpga_get_sys_ctrl_tx_sample_gap (caribou_fpga_st* dev, uint8_t *gap)
{
.rw = caribou_fpga_rw_read,
.mid = caribou_fpga_mid_sys_ctrl,
.ioc = IOC_SYS_CTRL_SYS_TX_SAMPLE_GAP
.ioc = IOC_SYS_CTRL_TX_SAMPLE_GAP
};
*gap = 0;
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), gap);
uint8_t actual_gap = 0;
int ret = caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &actual_gap);
if (gap) *gap = actual_gap & 0xF;
return ret;
}
//--------------------------------------------------------------
int caribou_fpga_set_sys_ctrl_sync_source (caribou_fpga_st* dev, caribou_fpga_sync_source_en rx_09,
caribou_fpga_sync_source_en rx_24,
caribou_fpga_sync_source_en tx_09,
caribou_fpga_sync_source_en tx_24)
{
uint8_t actual_val = 0;
uint8_t temp = 0;
CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_sys_ctrl_sync_source");
// read before write
caribou_fpga_opcode_st oc =
{
.rw = caribou_fpga_rw_read,
.mid = caribou_fpga_mid_sys_ctrl,
.ioc = IOC_SYS_CTRL_TX_SAMPLE_GAP,
};
int ret = caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &actual_val);
if (ret != 0) return -1;
temp = actual_val & 0xF;
uint8_t cur_rx_09 = (actual_val >> 4) & 0x1;
uint8_t cur_rx_24 = (actual_val >> 5) & 0x1;
uint8_t cur_tx_09 = (actual_val >> 6) & 0x1;
uint8_t cur_tx_24 = (actual_val >> 7) & 0x1;
if (rx_09 != caribou_fpga_sync_src_no_change) cur_rx_09 = rx_09 & 0x1;
if (rx_24 != caribou_fpga_sync_src_no_change) cur_rx_24 = rx_24 & 0x1;
if (tx_09 != caribou_fpga_sync_src_no_change) cur_tx_09 = tx_09 & 0x1;
if (tx_24 != caribou_fpga_sync_src_no_change) cur_tx_24 = tx_24 & 0x1;
temp |= cur_rx_09 << 4;
temp |= cur_rx_24 << 5;
temp |= cur_tx_09 << 6;
temp |= cur_tx_24 << 7;
oc.rw = caribou_fpga_rw_write;
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &temp);
}
//--------------------------------------------------------------
int caribou_fpga_get_sys_ctrl_sync_source (caribou_fpga_st* dev, caribou_fpga_sync_source_en *rx_09,
caribou_fpga_sync_source_en *rx_24,
caribou_fpga_sync_source_en *tx_09,
caribou_fpga_sync_source_en *tx_24)
{
uint8_t temp = 0;
CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_sys_ctrl_sync_source");
// read before write
caribou_fpga_opcode_st oc =
{
.rw = caribou_fpga_rw_read,
.mid = caribou_fpga_mid_sys_ctrl,
.ioc = IOC_SYS_CTRL_TX_SAMPLE_GAP,
};
int ret = caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &temp);
if (ret != 0) return -1;
if (rx_09) *rx_09 = (temp >> 4) & 0x1;
if (rx_24) *rx_24 = (temp >> 5) & 0x1;
if (tx_09) *tx_09 = (temp >> 6) & 0x1;
if (tx_24) *tx_24 = (temp >> 7) & 0x1;
return 0;
}
//--------------------------------------------------------------
int caribou_fpga_set_sys_ctrl_soft_sync_value (caribou_fpga_st* dev, uint8_t rx_09,
uint8_t rx_24,
uint8_t tx_09,
uint8_t tx_24)
{
uint8_t temp = (rx_09 & 0xf) | ((tx_09 & 0xf) << 1) | ((rx_24 & 0xf) << 2) | ((tx_24 & 0xf) << 3);
CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_sys_ctrl_soft_sync_value");
// read before write
caribou_fpga_opcode_st oc =
{
.rw = caribou_fpga_rw_write,
.mid = caribou_fpga_mid_sys_ctrl,
.ioc = IOC_SYS_CTRL_SOFT_SYNC,
};
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &temp);
}
//--------------------------------------------------------------
// I/O Controller
int caribou_fpga_set_io_ctrl_mode (caribou_fpga_st* dev, uint8_t debug_mode, caribou_fpga_io_ctrl_rfm_en rfm)
{
@ -445,8 +557,8 @@ int caribou_fpga_get_io_ctrl_mode (caribou_fpga_st* dev, uint8_t* debug_mode, ca
uint8_t mode = 0;
caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &mode);
*debug_mode = mode & 0x3;
*rfm = (mode >> 2) & 0x7;
if (debug_mode) *debug_mode = mode & 0x3;
if (rfm) *rfm = (mode >> 2) & 0x7;
return 0;
}
@ -512,8 +624,12 @@ int caribou_fpga_get_io_ctrl_pmod_dir (caribou_fpga_st* dev, uint8_t *dir)
.mid = caribou_fpga_mid_io_ctrl,
.ioc = IOC_IO_CTRL_PMOD_DIR
};
*dir = 0;
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), dir);
if (dir)
{
*dir = 0;
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), dir);
}
return -1;
}
//--------------------------------------------------------------
@ -540,8 +656,12 @@ int caribou_fpga_get_io_ctrl_pmod_val (caribou_fpga_st* dev, uint8_t *val)
.mid = caribou_fpga_mid_io_ctrl,
.ioc = IOC_IO_CTRL_PMOD_VAL
};
*val = 0;
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), val);
if (val)
{
*val = 0;
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), val);
}
return -1;
}
//--------------------------------------------------------------
@ -568,8 +688,12 @@ int caribou_fpga_get_io_ctrl_rf_state (caribou_fpga_st* dev, caribou_fpga_rf_pin
.mid = caribou_fpga_mid_io_ctrl,
.ioc = IOC_IO_CTRL_RF_PIN
};
memset(pins, 0, sizeof(caribou_fpga_rf_pin_st));
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), (uint8_t*)pins);
if (pins)
{
memset(pins, 0, sizeof(caribou_fpga_rf_pin_st));
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), (uint8_t*)pins);
}
return -1;
}
//--------------------------------------------------------------
@ -583,8 +707,12 @@ int caribou_fpga_get_smi_ctrl_fifo_status (caribou_fpga_st* dev, caribou_fpga_sm
.mid = caribou_fpga_mid_smi_ctrl,
.ioc = IOC_SMI_CTRL_FIFO_STATUS
};
memset(status, 0, sizeof(caribou_fpga_smi_fifo_status_st));
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), (uint8_t*)status);
if (status)
{
memset(status, 0, sizeof(caribou_fpga_smi_fifo_status_st));
return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), (uint8_t*)status);
}
return -1;
}
//--------------------------------------------------------------

Wyświetl plik

@ -98,6 +98,20 @@ typedef enum
caribou_fpga_smi_channel_1 = 1,
} caribou_fpga_smi_channel_en;
/**
* @brief Syncronization bit (metadata) source. Either software
* setting using "caribou_fpga_set_sys_ctrl_soft_sync_value"
* or by using an external pulse on the PMOD 6/7 pins.
* If no change is needed on a specific sync source,
* "caribou_fpga_sync_src_no_change" should be used
*/
typedef enum
{
caribou_fpga_sync_src_soft = 0,
caribou_fpga_sync_src_pmod = 1,
caribou_fpga_sync_src_no_change = 2,
} caribou_fpga_sync_source_en;
#pragma pack()
/**
@ -154,6 +168,19 @@ int caribou_fpga_set_debug_modes (caribou_fpga_st* dev, bool dbg_fifo_push, bool
int caribou_fpga_set_sys_ctrl_tx_sample_gap (caribou_fpga_st* dev, uint8_t gap);
int caribou_fpga_get_sys_ctrl_tx_sample_gap (caribou_fpga_st* dev, uint8_t *gap);
int caribou_fpga_set_sys_ctrl_sync_source (caribou_fpga_st* dev, caribou_fpga_sync_source_en rx_09,
caribou_fpga_sync_source_en rx_24,
caribou_fpga_sync_source_en tx_09,
caribou_fpga_sync_source_en tx_24);
int caribou_fpga_get_sys_ctrl_sync_source (caribou_fpga_st* dev, caribou_fpga_sync_source_en *rx_09,
caribou_fpga_sync_source_en *rx_24,
caribou_fpga_sync_source_en *tx_09,
caribou_fpga_sync_source_en *tx_24);
int caribou_fpga_set_sys_ctrl_soft_sync_value (caribou_fpga_st* dev, uint8_t rx_09,
uint8_t rx_24,
uint8_t tx_09,
uint8_t tx_24);
// I/O Controller
int caribou_fpga_set_io_ctrl_mode (caribou_fpga_st* dev, uint8_t debug_mode, caribou_fpga_io_ctrl_rfm_en rfm);
int caribou_fpga_get_io_ctrl_mode (caribou_fpga_st* dev, uint8_t *debug_mode, caribou_fpga_io_ctrl_rfm_en *rfm);

Wyświetl plik

@ -18,12 +18,13 @@
#include "cariboulite_events.h"
#include "cariboulite_setup.h"
#define GET_MODEM_CH(rad_ch) ((rad_ch)==cariboulite_channel_s1g ? at86rf215_rf_channel_900mhz : at86rf215_rf_channel_2400mhz)
#define GET_SMI_CH(rad_ch) ((rad_ch)==cariboulite_channel_s1g ? caribou_smi_channel_900 : caribou_smi_channel_2400)
static float sample_rate_middles[] = {3000, 1666, 1166, 900, 733, 583, 450};
static float rx_bandwidth_middles[] = {225, 281, 356, 450, 562, 706, 893, 1125, 1406, 1781, 2250};
static float tx_bandwidth_middles[] = {90, 112, 142, 180, 225, 282, 357, 450, 562, 712, 900};
static float sample_rate_middles[] = {3000e3, 1666e3, 1166e3, 900e3, 733e3, 583e3, 450e3};
static float rx_bandwidth_middles[] = {225e3, 281e3, 356e3, 450e3, 562e3, 706e3, 893e3, 1125e3, 1406e3, 1781e3, 2250e3};
static float tx_bandwidth_middles[] = {90e3, 112e3, 142e3, 180e3, 225e3, 282e3, 357e3, 450e3, 562e3, 712e3, 900e3};
//=========================================================================
@ -187,8 +188,30 @@ int cariboulite_radio_set_rx_bandwidth(cariboulite_radio_state_st* radio,
cariboulite_radio_rx_bw_en rx_bw)
{
cariboulite_radio_f_cut_en fcut = cariboulite_radio_rx_f_cut_half_fs;
/*if (rx_bw == cariboulite_radio_rx_bw_2500KHz || rx_bw == cariboulite_radio_rx_bw_2000KHz)
{
fcut = cariboulite_radio_rx_f_cut_half_fs; // 2MHz cuttof
}
else if (rx_bw == cariboulite_radio_rx_bw_1562KHz ||
rx_bw == cariboulite_radio_rx_bw_1250KHz ||
rx_bw == cariboulite_radio_rx_bw_1000KHz)
{
fcut = cariboulite_radio_rx_f_cut_0_75_half_fs; // 1.5MHz cuttof
}
else if (rx_bw == cariboulite_radio_rx_bw_787KHz ||
rx_bw == cariboulite_radio_rx_bw_625KHz)
{
fcut = cariboulite_radio_rx_f_cut_0_5_half_fs; // 1MHz cuttof
}
else
{
fcut = cariboulite_radio_rx_f_cut_0_25_half_fs; // 500kHz cuttof
}*/
radio->rx_fcut = fcut;
at86rf215_radio_set_rx_bw_samp_st cfg =
{
.inverter_sign_if = 0,
@ -197,8 +220,8 @@ int cariboulite_radio_set_rx_bandwidth(cariboulite_radio_state_st* radio,
// to channel scheme. This increases the IF frequency to max 2.5MHz
// thus places the internal LO fasr away from the signal => lower noise
.bw = (at86rf215_radio_rx_bw_en)rx_bw,
.fcut = (at86rf215_radio_f_cut_en)radio->rx_fcut, // keep the same
.fs = (at86rf215_radio_sample_rate_en)radio->rx_fs, // keep the same
.fcut = (at86rf215_radio_f_cut_en)radio->rx_fcut,
.fs = (at86rf215_radio_sample_rate_en)radio->rx_fs,
};
at86rf215_radio_set_rx_bandwidth_sampling(&radio->sys->modem, GET_MODEM_CH(radio->type), &cfg);
radio->rx_bw = rx_bw;
@ -1053,12 +1076,11 @@ int cariboulite_radio_activate_channel(cariboulite_radio_state_st* radio,
// then deactivate the modem's stream
cariboulite_radio_set_modem_state(radio, cariboulite_radio_state_cmd_trx_off);
ret = caribou_smi_set_driver_streaming_state(&radio->sys->smi, smi_stream_idle);
// DEACTIVATION
if (!activate)
{
// if we deactivate, first shut off the smi stream
ret = caribou_smi_set_driver_streaming_state(&radio->sys->smi, smi_stream_idle);
return ret;
}
@ -1088,14 +1110,7 @@ int cariboulite_radio_activate_channel(cariboulite_radio_state_st* radio,
// Activate the channel according to the configurations
// RX on both channels looks the same
if (radio->channel_direction == cariboulite_channel_dir_rx)
{
// Setup the IQ stream properties
smi_stream_state_en smi_state = smi_stream_idle;
if (radio->smi_channel_id == caribou_smi_channel_900)
smi_state = smi_stream_rx_channel_0;
else if (radio->smi_channel_id == caribou_smi_channel_2400)
smi_state = smi_stream_rx_channel_1;
{
at86rf215_iq_interface_config_st modem_iq_config = {
.loopback_enable = radio->tx_loopback_anabled,
.drv_strength = at86rf215_iq_drive_current_4ma,
@ -1105,11 +1120,29 @@ int cariboulite_radio_activate_channel(cariboulite_radio_state_st* radio,
.radio24_mode = at86rf215_iq_if_mode,
.clock_skew = at86rf215_iq_clock_data_skew_4_906ns,
};
at86rf215_setup_iq_if(&radio->sys->modem, &modem_iq_config);
// Setup the IQ stream properties
smi_stream_state_en smi_state = smi_stream_idle;
if (radio->smi_channel_id == caribou_smi_channel_900)
{
modem_iq_config.radio09_mode = at86rf215_iq_if_mode;
modem_iq_config.radio24_mode = at86rf215_baseband_mode;
modem_iq_config.clock_skew = at86rf215_iq_clock_data_skew_4_906ns;
smi_state = smi_stream_rx_channel_0;
}
else if (radio->smi_channel_id == caribou_smi_channel_2400)
{
modem_iq_config.radio09_mode = at86rf215_baseband_mode;
modem_iq_config.radio24_mode = at86rf215_iq_if_mode;
modem_iq_config.clock_skew = at86rf215_iq_clock_data_skew_4_906ns;
smi_state = smi_stream_rx_channel_1;
}
at86rf215_setup_iq_if(&radio->sys->modem, &modem_iq_config);
// configure FPGA with the correct rx channel
caribou_fpga_set_smi_channel (&radio->sys->fpga, radio->type == cariboulite_channel_s1g? caribou_fpga_smi_channel_0 : caribou_fpga_smi_channel_1);
//caribou_fpga_set_io_ctrl_dig (&radio->sys->fpga, radio->type == cariboulite_channel_s1g? 0 : 1, 0);
caribou_fpga_set_smi_ctrl_data_direction(&radio->sys->fpga, 1);
// turn on the modem RX
cariboulite_radio_set_modem_state(radio, cariboulite_radio_state_cmd_rx);
@ -1135,7 +1168,7 @@ int cariboulite_radio_activate_channel(cariboulite_radio_state_st* radio,
.tx_control_with_iq_if = !radio->cw_output,
.radio09_mode = at86rf215_iq_if_mode,
.radio24_mode = at86rf215_iq_if_mode,
.clock_skew = at86rf215_iq_clock_data_skew_4_906ns,
.clock_skew = at86rf215_iq_clock_data_skew_2_906ns,
};
at86rf215_setup_iq_if(&radio->sys->modem, &modem_iq_config);
@ -1187,6 +1220,7 @@ int cariboulite_radio_activate_channel(cariboulite_radio_state_st* radio,
// apply the state
caribou_smi_set_driver_streaming_state(&radio->sys->smi, smi_stream_tx_channel);
caribou_fpga_set_smi_ctrl_data_direction (&radio->sys->fpga, 0);
//cariboulite_radio_set_modem_state(radio, cariboulite_radio_state_cmd_tx);
}
}

Wyświetl plik

@ -122,11 +122,13 @@ static void usage(void)
"\t[-F force fpga reprogramming (default: '0')]\n"
"\t[-M write metadata (default: '0')]\n"
"\tfilename ('-' dumps samples to stdout)\n\n"
"Example:\n"
"\t1. Sample S1G channel at 905MHz into filename capture.bin\n"
"\t\tcariboulite_util -c 0 -f 905000000 capture.bin\n"
"\t2. Sample S1G channel at 905MHz into filename capture.bin, only 30000 samples\n"
"\t\tcariboulite_util -c 0 -f 905000000 -n 30000 capture.bin\n\n");
"Example (CS16 files readable by 'inspectrum' analyzer):\n"
"\t1. Sample S1G channel at 905MHz into filename capture.cs16\n"
"\t\tcariboulite_util -c 0 -f 905000000 capture.cs16\n"
"\t2. Sample HiF channel at 2410MHz into filename capture_hif.cs16\n"
"\t\tcariboulite_util -c 1 -f 2410000000 capture_hif.cs16\n"
"\t3. Sample S1G channel at 905MHz into filename capture.cs16, only 30000 samples\n"
"\t\tcariboulite_util -c 0 -f 905000000 -n 30000 capture.cs16\n\n");
exit(1);
}

Wyświetl plik

@ -157,7 +157,7 @@ int rffc507x_init( rffc507x_st* dev,
set_RFFC507X_CTMAX(dev, 127);
set_RFFC507X_P2CTV(dev, 12);
set_RFFC507X_FULLD(dev, 0);*/
set_RFFC507X_P2MIXIDD(dev, 4);
set_RFFC507X_P2MIXIDD(dev, 5);
// Others
set_RFFC507X_LDEN(dev, 1);