87 lines
2.4 KiB
C++
87 lines
2.4 KiB
C++
/*
|
|
* mcp3008.cpp
|
|
*
|
|
* Created on: 17.07.2018
|
|
* Author: eyck
|
|
*/
|
|
|
|
#include "sysc/top/mcp3008.h"
|
|
|
|
#include <scc/report.h>
|
|
#include <util/ities.h>
|
|
|
|
namespace sysc {
|
|
|
|
mcp3008::mcp3008(sc_core::sc_module_name nm)
|
|
: sc_core::sc_module(nm)
|
|
, NAMED(sck_i)
|
|
, NAMED(miso_o)
|
|
, NAMED(mosi_i)
|
|
, NAMED(cs_i)
|
|
, NAMED(vref_i)
|
|
, NAMED(ch_i, 8)
|
|
, last_tx_start(sc_core::SC_ZERO_TIME)
|
|
{
|
|
sck_i.register_nb_transport([this](tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay)
|
|
-> tlm::tlm_sync_enum{
|
|
return tlm::TLM_COMPLETED;
|
|
});
|
|
|
|
mosi_i.register_nb_transport([this](tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay)
|
|
-> tlm::tlm_sync_enum{
|
|
if(cs_v==sc_dt::Log_0)
|
|
return receive(gp, phase, delay);
|
|
});
|
|
|
|
cs_i.register_nb_transport([this](tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay)
|
|
-> tlm::tlm_sync_enum{
|
|
if(cs_v!=sc_dt::Log_0 && gp.get_value()==sc_dt::Log_0){
|
|
idx=0; // falling edge
|
|
rx_bits=0;
|
|
}
|
|
cs_v=gp.get_value();
|
|
return tlm::TLM_COMPLETED;
|
|
});
|
|
}
|
|
|
|
mcp3008::~mcp3008() {
|
|
}
|
|
|
|
tlm::tlm_sync_enum mcp3008::receive(tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay) {
|
|
gp.get_extension(ext);
|
|
if(ext){
|
|
if( ext->start_time!=last_tx_start){
|
|
assert(ext->tx.data_bits==8);
|
|
rx_bytes[idx]=bit_sub<0,8>(ext->tx.m2s_data);
|
|
if(idx==1)
|
|
do_conversion();
|
|
ext->tx.s2m_data=tx_bytes[idx];
|
|
ext->tx.s2m_data_valid=true;
|
|
idx++;
|
|
last_tx_start=ext->start_time;
|
|
}
|
|
}
|
|
return tlm::TLM_COMPLETED;
|
|
}
|
|
|
|
void mcp3008::do_conversion() {
|
|
if(rx_bytes[0]==0x1){
|
|
auto mode = bit_sub<7,1>(rx_bytes[1]);
|
|
auto channel = bit_sub<4,3>(rx_bytes[1]);
|
|
auto vref=vref_i.read();
|
|
if(mode){ // single ended
|
|
auto inp = ch_i[channel].read();
|
|
auto norm = inp/vref*1024.0;
|
|
auto res = static_cast<int>(norm);
|
|
CLOG(DEBUG, SystemC)<<"Converting "<<inp<<" to "<<norm<<" as int "<<res;
|
|
tx_bytes[1]=bit_sub<8,2>(res);
|
|
tx_bytes[2]=bit_sub<0,8>(res);
|
|
} else {
|
|
tx_bytes[1]=0;
|
|
tx_bytes[2]=0;
|
|
}
|
|
}
|
|
}
|
|
|
|
} /* namespace sysc */
|