126 lines
3.0 KiB
C++
126 lines
3.0 KiB
C++
#include <random>
|
|
#include <cmath>
|
|
|
|
#include "Vautoapproach_sim.h"
|
|
#include "../testbench.hpp"
|
|
|
|
/* TODO: generalize so bram_interface_sim can use it.
|
|
* This should make a triangle wave.
|
|
*/
|
|
class RefreshModule {
|
|
uint32_t *store_32;
|
|
size_t word_amnt;
|
|
bool pending_refresh_start;
|
|
|
|
public:
|
|
void posedge(uint8_t &refresh_start, uint32_t &start_addr,
|
|
uint8_t refresh_finished) {
|
|
if (refresh_start && refresh_finished) {
|
|
refresh_start = 0;
|
|
} else if (pending_refresh_start && !refresh_start) {
|
|
pending_refresh_start = false;
|
|
refresh_start = 1;
|
|
}
|
|
}
|
|
|
|
RefreshModule(size_t _word_amnt, size_t _start_addr)
|
|
: word_amnt{_word_amnt}
|
|
, start_addr{_start_addr} {
|
|
store_32 = new uint32_t[_start_addr];
|
|
for (size_t i = 0; i < start_addr; i++) {
|
|
/* 0xFFFFF is the maximum DAC value */
|
|
store_32[i] = 0xFFFFF*max(double)i/start_addr;
|
|
}
|
|
pending_refresh_start = true;
|
|
}
|
|
|
|
~RefreshModule() {
|
|
delete[] store_32;
|
|
}
|
|
};
|
|
|
|
/* TODO: make generic SPI delay class because this code has been duplicated
|
|
* many times over now. This function is also similar to the control loop
|
|
* ADC simulation. */
|
|
class GaussianZPiezo {
|
|
std::default_random_engine generator;
|
|
std::normal_distribution<> dist;
|
|
double scale;
|
|
double setpt;
|
|
double midpt;
|
|
double stretch;
|
|
|
|
double sample() {return scale*dist(generator);}
|
|
|
|
GaussianZPiezo(double scale, double mean, double dev, double setpt,
|
|
double midpt, double stretch, int seed,
|
|
uint16_t dac_wait_count,
|
|
uint16_t adc_wait_count)
|
|
: scale{scale}, dist{mean,dev}, generator{},
|
|
, setpt{setpt}, midpt{midpt}, stretch{stretch},
|
|
, dac_wait_count_max{dac_wait_count}
|
|
, adc_wait_count_max{adc_wait_count} {
|
|
if (seed < 0) {
|
|
std::random_device rd;
|
|
generator.seed(rd());
|
|
} else {
|
|
generator.seed(seed);
|
|
}
|
|
}
|
|
/* Sigmoid function. This function is
|
|
|
|
c(x-d)
|
|
f(x) = A*-------------------
|
|
sqrt(1+(c(x-d))^2)
|
|
|
|
where A is the setpoint and c is how compressed the sigmoid is.
|
|
*/
|
|
|
|
double f(uint32_t x) {
|
|
double x_shift = x - midpt + sample();
|
|
return setpt*stretch*x_shift/sqrt(fma(x_shift,x_shift,1));
|
|
}
|
|
|
|
public:
|
|
|
|
void posedge(uint8_t &dac_finished, uint8_t dac_arm,
|
|
uint32_t dac_out,
|
|
uint8_t &adc_finished, uint8_t adc_arm,
|
|
uint32_t &adc_out) {
|
|
if (adc_arm && adc_wait_counter == adc_wait_counter_max &&
|
|
!adc_finished) {
|
|
adc_finished = 1;
|
|
adc_out = sample();
|
|
} else if (!adc_arm) {
|
|
adc_finished = 0;
|
|
adc_wait_counter = 0;
|
|
} else {
|
|
adc_wait_counter++;
|
|
}
|
|
|
|
if (dac_arm && dac_wait_counter == dac_wait_counter_max &&
|
|
!dac_finished) {
|
|
dac_finished = 1;
|
|
}
|
|
};
|
|
|
|
class AA_TB : TB<Vautoapproach_sim> {
|
|
RefreshModule refresh;
|
|
GaussianZPiezo piezo;
|
|
|
|
void posedge() override;
|
|
AA_TB(size_t word_amnt, uint32_t start_addr)
|
|
: refresh{word_amnt, start_addr} {}
|
|
|
|
~AA_TB() {}
|
|
};
|
|
|
|
AA_TB::posedge() {
|
|
refresh.posedge(mod.refresh_start, mod.start_addr,
|
|
mod.refresh_finished);
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
return 0;
|
|
}
|