OpenCores
URL https://opencores.org/ocsvn/openarty/openarty/trunk

Subversion Repositories openarty

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openarty/trunk/bench
    from Rev 33 to Rev 34
    Reverse comparison

Rev 33 → Rev 34

/cpp/Makefile
37,18 → 37,23
##
 
CXX := g++
FLAGS := -Wall -Og -g
OBJDIR := obj-pc
RTLD := ../../rtl
VERILATOR_ROOT ?= $(shell bash -c 'verilator -V|grep VERILATOR_ROOT | head -1 | sed -e " s/^.*=\s*//"')
VROOT := $(VERILATOR_ROOT)
GFXFLAGS:= `pkg-config gtkmm-3.0 --cflags`
GFXLIBS := `pkg-config gtkmm-3.0 --cflags --libs`
FLAGS := -Wall -Og -g
INCS := -I$(RTLD)/obj_dir/ -I$(RTLD) -I$(VROOT)/include
SOURCES := eqspiflashsim.cpp eqspiflash_tb.cpp enetctrlsim.cpp \
SOURCES := fastmaster_tb.cpp eqspiflashsim.cpp eqspiflash_tb.cpp \
oledsim.cpp enetctrlsim.cpp \
memsim.cpp sdspisim.cpp uartsim.cpp ddrsdramsim.cpp
HEADERS := ddrsdramsim.h enetctrlsim.h eqspiflashsim.h memsim.h \
oledsim.h pipecmdr.h port.h sdspisim.h testb.h uartsim.h
VOBJDR := $(RTLD)/obj_dir
VLIB := $(VROOT)/include/verilated.cpp
SIMSRCS := enetctrlsim.cpp eqspiflashsim.cpp \
memsim.cpp sdspisim.cpp uartsim.cpp
memsim.cpp sdspisim.cpp uartsim.cpp oledsim.cpp
SIMOBJ := $(subst .cpp,.o,$(SIMSRCS))
SIMOBJS:= $(addprefix $(OBJDIR)/,$(SIMOBJ))
all: $(OBJDIR)/ busmaster_tb eqspiflash_tb enetctrl_tb
57,8 → 62,26
@bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi"
 
$(OBJDIR)/%.o: %.cpp
$(CXX) $(FLAGS) -c $^ -o $@
$(CXX) $(FLAGS) -c $< -o $@
 
.PHONY: oledsim.o
oledsim.o: $(OBJDIR)/oledsim.o
$(OBJDIR)/oledsim.o: oledsim.cpp
$(CXX) $(FLAGS) $(GFXFLAGS) -c $< -o $@
 
# While busmaster_tb.o isnt really dependent upon fastmaster_tb.o, this
# makes certain that all of the dependencies of fastmaster_tb are captured
# in busmaster. Hence, if fastmaster_tb is remade/rebuilt because one of
# its dependencies change, so too is busmaster_tb.
#
$(OBJDIR)/busmaster_tb.o: fastmaster_tb.cpp
$(CXX) $(FLAGS) $(GFXFLAGS) $(INCS) -c $< -o $@
 
$(OBJDIR)/fastmaster_tb.o: fastmaster_tb.cpp
$(CXX) -DFASTCLK $(FLAGS) $(GFXFLAGS) $(INCS) -c $< -o $@
 
 
 
eqspiflash_tb: eqspiflash_tb.cpp $(OBJDIR)/eqspiflashsim.o $(VOBJDR)/Veqspiflash__ALL.a
$(CXX) $(FLAGS) $(INCS) $^ $(VOBJDR)/Veqspiflash__ALL.a $(VLIB) -o $@
 
65,15 → 88,37
enetctrl_tb: enetctrl_tb.cpp $(OBJDIR)/enetctrlsim.o $(VOBJDR)/Venetctrl__ALL.a
$(CXX) $(FLAGS) $(INCS) $^ $(VOBJDR)/Venetctrl__ALL.a $(VLIB) -o $@
 
fastmaster_tb:fastmaster_tb.cpp $(SIMOBJS) $(VOBJDR)/Vfastmaster__ALL.a
$(CXX) -DFASTCLK $(FLAGS) $(INCS) $^ $(VOBJDR)/Vfastmaster__ALL.a $(VLIB) -o $@
busmaster_tb:fastmaster_tb.cpp $(SIMOBJS) $(VOBJDR)/Vbusmaster__ALL.a
$(CXX) $(FLAGS) $(INCS) $^ $(VOBJDR)/Vbusmaster__ALL.a $(VLIB) -o $@
fastmaster_tb: $(OBJDIR)/fastmaster_tb.o $(SIMOBJS) $(VOBJDR)/Vfastmaster__ALL.a
$(CXX) $(GFXLIBS) $^ $(VOBJDR)/Vfastmaster__ALL.a $(VLIB) -o $@
busmaster_tb: $(OBJDIR)/busmaster_tb.o $(SIMOBJS) $(VOBJDR)/Vbusmaster__ALL.a
$(CXX) $(GFXLIBS) $(INCS) $^ $(VOBJDR)/Vbusmaster__ALL.a $(VLIB) $(GFXLIBS) -o $@
 
define build-depends
@echo "Building dependency file(s)"
@$(CXX) $(GFXFLAGS) $(INCS) -MM $(SOURCES) > $(OBJDIR)/xdepends.txt
@sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt \
| sed -e 's/fastmaster_tb.o/busmaster_tb.o/g' \
> $(OBJDIR)/depends.txt
@rm $(OBJDIR)/xdepends.txt
endef
 
tags: $(SOURCES) $(HEADERS)
@echo "Generating tags"
@ctags $(SOURCES) $(HEADERS)
 
.PHONY: clean
clean:
rm -rf $(OBJDIR)/
rm -f ./eqspiflash_tb
rm -f ./enetctrl_tb
rm -f ./fastmaster_tb
rm -f ./busmaster_tb
 
.PHONY: depends
depends:
$(build-depends)
 
$(OBJDIR)/depends.txt: $(OBJDIR)/ $(SOURCES) $(HEADERS)
$(build-depends)
 
-include $(OBJDIR)/depends.txt
/cpp/fastmaster_tb.cpp
63,6 → 63,9
#include "uartsim.h"
#include "enetctrlsim.h"
#include "memsim.h"
// #ifdef OLEDSIM
#include "oledsim.h"
// #endif
 
#include "port.h"
 
77,11 → 80,16
ENETCTRLSIM *m_mid;
UARTSIM m_uart;
MEMSIM m_ram;
#ifdef OLEDSIM_H
OLEDWIN m_oled;
#endif
 
unsigned m_last_led, m_last_pic, m_last_tx_state, m_net_ticks;
time_t m_start_time;
bool m_last_writeout, m_cpu_started;
int m_last_bus_owner, m_busy;
unsigned long m_gps_err, m_gps_step, m_gps_newstep;
unsigned m_gps_stepc;
 
TESTBENCH(void) : PIPECMDR(FPGAPORT),
m_uart(FPGAPORT+1), m_ram(1<<26)
89,6 → 97,9
m_start_time = time(NULL);
m_mid = new ENETCTRLSIM;
m_cpu_started =false;
#ifdef OLEDSIM_H
Glib::signal_idle().connect(sigc::mem_fun((*this),&TESTBENCH::on_tick));
#endif
}
 
void setsdcard(const char *fn) {
97,6 → 108,11
printf("LOADING SDCARD FROM: \'%s\'\n", fn);
}
 
bool on_tick(void) {
tick();
return true; // Keep going 'til the kingdom comes
}
 
void tick(void) {
if ((m_tickcount & ((1<<28)-1))==0) {
double ticks_per_second = m_tickcount;
109,6 → 125,12
}
 
// Set up the bus before any clock tick
#ifdef OLEDSIM_H
m_oled(m_core->o_oled_pmoden, m_core->o_oled_reset_n,
m_core->o_oled_vccen, m_core->o_oled_cs_n,
m_core->o_oled_sck, m_core->o_oled_dcn,
m_core->o_oled_mosi);
#endif
m_core->i_qspi_dat = m_flash(m_core->o_qspi_cs_n,
m_core->o_qspi_sck, m_core->o_qspi_dat);
 
159,6 → 181,8
#ifdef DEBUGGING_OUTPUT
bool writeout = false;
 
/*
// Ethernet triggers
if (m_core->o_net_tx_en)
writeout = true;
if (m_core->v__DOT__netctrl__DOT__n_rx_busy)
167,12 → 191,66
writeout = true;
if (m_core->v__DOT__netctrl__DOT__w_rxwr)
writeout = true;
*/
 
/*
// GPS Clock triggers
if (m_core->v__DOT__ppsck__DOT__tick)
writeout = true;
if (m_core->v__DOT__gps_step != m_gps_step) {
writeout = true;
// printf("STEP");
} if (m_core->v__DOT__gps_err != m_gps_err) {
writeout = true;
// printf("ERR");
} if (m_core->v__DOT__ppsck__DOT__step_correction != m_gps_stepc) {
writeout = true;
// printf("DSTP");
} if (m_core->v__DOT__ppsck__DOT__getnewstep__DOT__genblk2__DOT__genblk1__DOT__r_out != m_gps_newstep)
writeout = true;
*/
m_gps_step = m_core->v__DOT__gps_step;
m_gps_err = m_core->v__DOT__gps_err;
m_gps_stepc= m_core->v__DOT__ppsck__DOT__step_correction;
m_gps_newstep=m_core->v__DOT__ppsck__DOT__getnewstep__DOT__genblk2__DOT__genblk1__DOT__r_out;
 
if (m_core->o_oled_cs_n == 0)
writeout = true;
if (m_core->o_oled_sck == 0)
writeout = true;
if (m_core->v__DOT__rgbctrl__DOT__dev_wr)
writeout = true;
if (m_core->v__DOT__rgbctrl__DOT__r_busy)
writeout = true;
if (m_core->v__DOT__rgbctrl__DOT__dev_busy)
writeout = true;
 
 
/*
if (m_core->v__DOT__ppsck__DOT__err_tick)
writeout = true;
if (m_core->v__DOT__ppsck__DOT__sub_tick)
writeout = true;
if (m_core->v__DOT__ppsck__DOT__shift_tick)
writeout = true;
if (m_core->v__DOT__ppsck__DOT__fltr_tick)
writeout = true;
if (m_core->v__DOT__ppsck__DOT__config_tick)
writeout = true;
if (m_core->v__DOT__ppsck__DOT__mpy_sync)
writeout = true;
if (m_core->v__DOT__ppsck__DOT__mpy_sync_two)
writeout = true;
if (m_core->v__DOT__ppsck__DOT__delay_step_clk)
writeout = true;
*/
 
// if (m_core->v__DOT__wbu_cyc)
// writeout = true;
// if (m_core->v__DOT__dwb_cyc)
// writeout = true;
 
// Write out if the CPU is active at all
if (m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__master_ce)
writeout = true;
if (m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__dbgv)
396,6 → 474,8
}
*/
 
/*
// Network debugging
printf("ETH[TX:%s%s%x%s]",
(m_core->i_net_tx_clk)?"CK":" ",
(m_core->o_net_tx_en)?" ":"(",
463,6 → 543,8
(m_core->v__DOT__netctrl__DOT__rxmaci__DOT__r_p)&0x0ff,
m_core->v__DOT__netctrl__DOT__w_rxmacd,
(m_core->v__DOT__netctrl__DOT__w_rxmac)?"!":" ");
*/
 
/*
// Flash debugging support
printf("%s/%s %s %s[%s%s%s%s%s] %s@%08x[%08x/%08x] -- SPI %s%s[%x/%x](%d,%d)",
532,6 → 614,68
*/
 
 
/*
// Debugging the GPS tracking circuit
printf("COUNT %016lx STEP %016lx+%08x->%016lx ERR %016lx %s",
m_core->v__DOT__gps_now,
m_core->v__DOT__gps_step,
m_core->v__DOT__ppsck__DOT__step_correction,
m_core->v__DOT__ppsck__DOT__getnewstep__DOT__genblk2__DOT__genblk1__DOT__r_out,
m_core->v__DOT__gps_err,
(m_core->v__DOT__ppsck__DOT__tick)?"TICK":" ");
*/
 
 
// Debug the OLED
 
{ const char *pwr; int pwrk;
if (m_core->o_oled_pmoden) {
if (!m_core->o_oled_reset_n)
pwr = "RST";
else if (m_core->o_oled_vccen)
pwr = "ON ";
else
pwr = "VIO";
} else if (m_core->o_oled_vccen) {
pwr = "ERR";
} else
pwr = "OFF";
pwrk = (m_core->o_oled_reset_n)?4:0;
pwrk|= (m_core->o_oled_vccen)?2:0;
pwrk|= (m_core->o_oled_pmoden);
// First the top-level ports
printf(" OLED[%s/%d,%s%s%s-%d]",
pwr, pwrk,
(!m_core->o_oled_cs_n)?"CS":" ",
(m_core->o_oled_sck)?"CK":" ",
(m_core->o_oled_dcn)?"/D":"/C",
(m_core->o_oled_mosi));
}
// Now the low-level internals
printf("LL[");
switch(m_core->v__DOT__rgbctrl__DOT__lwlvl__DOT__state){
case 0: printf("I,"); break;
case 1: printf("S,"); break;
case 2: printf("B,"); break;
case 3: printf("R,"); break;
case 4: printf("!,"); break;
case 5: printf(".,"); break;
default: printf("U%d",
m_core->v__DOT__rgbctrl__DOT__lwlvl__DOT__state);
}
printf("%2d,%s%2d,%08x]",
m_core->v__DOT__rgbctrl__DOT__lwlvl__DOT__spi_len,
(m_core->v__DOT__rgbctrl__DOT__lwlvl__DOT__pre_last_counter)?"P":" ",
 
m_core->v__DOT__rgbctrl__DOT__lwlvl__DOT__counter,
m_core->v__DOT__rgbctrl__DOT__lwlvl__DOT__r_word);
printf("[%s%s%s/%2d/%d]",
(m_core->v__DOT__rgbctrl__DOT__dev_wr)?"W":" ",
(m_core->v__DOT__rgbctrl__DOT__r_busy)?"BSY":" ",
(m_core->v__DOT__rgbctrl__DOT__dev_busy)?"D-BSY":" ",
m_core->v__DOT__rgbctrl__DOT__r_len,
m_core->v__DOT__rgbctrl__DOT__dev_len);
 
printf("\n"); fflush(stdout);
} m_last_writeout = writeout;
#endif
547,6 → 691,9
}
 
int main(int argc, char **argv) {
#ifdef OLEDSIM_H
Gtk::Main main_instance(argc, argv);
#endif
Verilated::commandArgs(argc, argv);
tb = new TESTBENCH;
 
558,8 → 705,12
else
tb->setsdcard("/dev/zero");
 
#ifdef OLEDSIM_H
Gtk::Main::run(tb->m_oled);
#else
while(1)
tb->tick();
#endif
 
exit(0);
}
/cpp/oledsim.cpp
0,0 → 1,531
////////////////////////////////////////////////////////////////////////////////
//
// Filename: oledsim.cpp
//
// Project: OpenArty, an entirely open SoC based upon the Arty platform
//
// Purpose: The goal of this module is very specifically to simulate the
// PModOLEDrgb using a GTKMM controlled window. I'm doing this on
// an Linux computer with X-Windows, although one GTKMM selling point is
// that it should work in Windows as well. I won't vouch for that, as I
// haven't tested under windows.
//
// Either way, this controller only implements *some* of the OLED commands.
// There were just too many commands for me to be able to write them in the
// short order that I needed to get a test up and running. Therefore, this
// simulator will validate all commands and assure you they are valid
// commands, but it will only respond to some. For specifics, see the
// do_command() section below.
//
// You may notice a lot of assert() calls within this code. This is half
// the purpose of the code: to verify that interactions, when the take
// place, are valid. The sad problem and effect of this is simply that
// when bugs are present, the error/warning messages are not that complete.
// If you find yourself dealing with such an error, please feel free to
// explain the assert better before asserting, and then send your
// contributions back to me so that others can benefit from your work.
// (Don't you love the GPL?)
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include "oledsim.h"
 
const int OLEDSIM::OLED_HEIGHT = 64, OLEDSIM::OLED_WIDTH = 96;
 
const int MICROSECOND = 81,
tMINRESET = 3 * MICROSECOND, // 3 uS
tCYCLE = 13, // 150 * NANOSECOND, clock cycle time
tAS = 4, // 40 * NANOSECOND, address setup time
tAH = 4, // 40 * NANOSECOND, address hold time
tCSS = 7, // 75 * NANOSECOND, chip select setup
tCSH = 5, // 60 * NANOSECOND, chip select hold
tCLKL = 7, // 75 * NANOSECOND, time the clock must be low
tCLKH = 7; // 75 * NANOSECOND, time the clock must be high
 
void OLEDSIM::on_realize() {
Gtk::DrawingArea::on_realize();
 
// We'll be doing all of our drawing on an off-screen bit map. Here,
// let's allocate that pixel map ...
m_pix = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24,
OLED_WIDTH, OLED_HEIGHT);
 
// and a graphics context to be used when drawing to it.
m_gc = Cairo::Context::create(m_pix);
 
// We'll start the pixel map filled with all black, as this is what
// my device looks like when I'm not doing anything with it.
m_gc->set_source_rgb(0.0,0.0,0.0); // Black
m_gc->rectangle(0, 0, OLED_WIDTH, OLED_HEIGHT);
m_gc->fill();
}
 
void OLEDSIM::get_preferred_width_vfunc(int &min, int &nw) const {
// GTKMM wants to know how big we want our window to be.
// Let's request a window twice as big as we need, but insist that
// it never be smaller than one pixel output per one pixel input.
//
min = OLED_WIDTH;
nw = OLED_WIDTH * 2;
}
 
void OLEDSIM::get_preferred_height_vfunc(int &min, int &nw) const {
//
// Same thing as above, but this time for height, not width.
//
min = OLED_HEIGHT;
nw = OLED_HEIGHT * 2;
}
 
void OLEDSIM::get_preferred_width_for_height_vfunc(int h, int &min, int &nw) const {
min = OLED_WIDTH;
int k = (h+(OLED_HEIGHT/2))/OLED_HEIGHT;
if (k <= 0)
k = 1;
nw = OLED_WIDTH * k;
}
 
void OLEDSIM::get_preferred_height_for_width_vfunc(int w, int &min, int &nw) const {
min = OLED_HEIGHT;
int k = (w+(OLED_WIDTH/2))/OLED_WIDTH;
if (k <= 0)
k = 1;
nw = OLED_HEIGHT * k;
}
 
/*
* This is our simulation function. This is the function that gets called at
* every tick of our controller within Verilator. At each tick (and not twice
* per tick), the outputs are gathered and sent our way. Here, we just decode
* the power and reset outputs, and send everything else to handle_io().
*/
void OLEDSIM::operator()(const int iopwr, const int rstn, const int dpwr,
const int csn, const int sck, const int dcn, const int mosi) {
if (!iopwr) {
if (m_state != OLED_OFF) {
m_state = OLED_OFF;
clear_to(0.0);
queue_draw_area(0,0,get_width(), get_height());
}
assert(!dpwr);
} else if (!rstn) {
if (m_state != OLED_RESET) {
m_state = OLED_RESET;
m_locked = true;
clear_to(0.1);
m_reset_clocks = 0;
queue_draw_area(0,0,get_width(), get_height());
} if (m_reset_clocks < tMINRESET)
m_reset_clocks++;
assert(csn);
assert(sck);
} else if (dpwr) {
if (m_state != OLED_POWERED) {
m_state = OLED_POWERED;
queue_draw_area(0,0,get_width(), get_height());
if (!csn) {
printf("OLED-ERR: CSN=%d, SCK=%d, DCN=%d, MOSI=%d, from %d,%d,%d\n",
csn, sck, dcn, mosi,
m_last_csn, m_last_sck, m_last_dcn);
}
assert(csn); // Can't power up with SPI active.
}
 
handle_io(csn, sck, dcn, mosi);
} else {
if (m_state != OLED_VIO) {
m_state = OLED_VIO;
queue_draw_area(0,0,OLED_WIDTH, OLED_HEIGHT);
}
handle_io(csn, sck, dcn, mosi);
}
}
 
/* handle_io()
*
* We only enter this function if the I/O is powered up and the device is out
* of reset. The device may (or may not) be on. Our purpose here is to decode
* the SPI commands into a byte sequence, kept in m_data with a length given by
* m_idx. Once a command has completed, we call do_command() to actually
* process the values received, the arguments, etc. and do something with them.
*
*/
void OLEDSIM::handle_io(const int csn, const int sck, const int dcn, const int mosi) {
if ((csn != m_last_csn)||(sck != m_last_sck)||(dcn != m_last_dcn))
printf("OLED: HANDLE-IO(%d,%d,%d,%d) @[%d]%d\n",
csn, sck, dcn, mosi, m_idx, m_bitpos);
if (csn) {
// CSN is high when the chip isn't selected.
if (!m_last_csn) {
// If the chip was just selected, it then means that our
// command just completed. Let's process it here.
printf("OLED: Ending a command\n");
assert(m_idx > 0);
assert((m_bitpos&7)==0);
do_command(m_last_dcn, m_idx, m_data);
 
m_bitpos = 0;
m_idx = 0;
for(int i=0; i<8; i++)
m_data[i] = 0;
assert(m_last_sck);
} if (!sck)
printf("OLED: CSN = %d, SCK = %d, DCN = %d, MOSI = %d, from %d, %d, %d\n",
csn, sck, dcn, mosi,
m_last_csn, m_last_sck, m_last_dcn);
assert(sck);
m_bitpos = 0;
m_idx = 0;
} else {
if (m_last_csn) {
assert((sck)&&(m_last_sck));
assert(m_last_sck);
printf("OLED: Starting a command\n");
}
 
/*
if (m_last_dcn != dcn) {
m_address_counts = 0;
} m_address_counts++;
*/
 
if ((sck)&&(!m_last_sck)) {
m_bitpos++;
m_data[m_idx] = (m_data[m_idx]<<1)|mosi;
printf("OLED: Accepted bit: m_data[%d] = %02x\n",
m_idx, m_data[m_idx]);
if (m_bitpos >= 8) {
m_idx++;
m_bitpos &= 7;
}
assert(m_idx < 3+4+4);
// assert(m_address_count > tCSS);
} else if ((!sck)&&(m_last_sck)) {
}
}
 
m_last_csn = csn;
m_last_sck = sck;
m_last_dcn = dcn;
}
 
void OLEDSIM::do_command(const int dcn, const int len, char *data) {
assert(len > 0);
assert(len <= 11);
 
printf("OLED: RECEIVED CMD(%02x) ", data[0]&0x0ff);
if (len > 1) {
printf(" - ");
for(int i=1; i<len-1; i++)
printf("%02x:", data[i]&0x0ff);
printf("%02x", data[len-1]&0x0ff);
printf("\n");
}
if (dcn) {
// Do something with the pixmap
double dr, dg, db;
 
if (m_format == OLED_65kCLR) {
int r, g, b;
assert(len == 2);
r = (data[0]>>3)&0x01f;
g = ((data[0]<<3)&0x038)|((data[1]>>5)&0x07);
b = ((data[1] )&0x01f);
 
dr = r / 31.0;
dg = g / 63.0;
db = b / 31.0;
} else {
printf("OLED: UNSUPPORTED COLOR FORMAT!\n");
dr = dg = db = 0.0;
} set_gddram(m_col, m_row, dr, dg, db);
if (!m_vaddr_inc) {
m_col++;
if (m_col > m_col_end) {
m_col = m_col_start;
m_row++;
if (m_row > m_row_end)
m_row = m_row_start;
}
} else {
m_row++;
if (m_row > m_row_end) {
m_row = m_row_start;
m_col++;
if (m_col > m_col_end)
m_col = m_col_start;
}
}
} else if (m_locked) {
if ((len == 2)&&((data[0]&0x0ff) == 0x0fd)&&(data[1] == 0x12)) {
m_locked = false;
printf("OLED: COMMANDS UNLOCKED\n");
} else {
printf("OLED: COMMAND IGNORED, IC LOCKED\n");
}
} else {
// Command word
switch((data[0])&0x0ff) {
case 0x15: // Setup column start and end address
assert(len == 3);
assert((data[1]&0x0ff) <= 95);
assert((data[2]&0x0ff) <= 95);
m_col_start = data[1]&0x0ff;
m_col_end = data[2]&0x0ff;
assert(m_col_end >= m_col_start);
m_col = m_col_start;
break;
case 0x75: // Setup row start and end address
assert(len == 3);
assert((data[1]&0x0ff) <= 63);
assert((data[2]&0x0ff) <= 63);
assert(m_row_end >= m_row_start);
m_row_start = data[1]&0x0ff;
m_row_end = data[2]&0x0ff;
break;
case 0x81: // Set constrast for all color "A" segment
assert(len == 2);
break;
case 0x82: // Set constrast for all color "B" segment
assert(len == 2);
break;
case 0x83: // Set constrast for all color "C" segment
assert(len == 2);
break;
case 0x87: // Set master current attenuation factor
assert(len == 2);
break;
case 0x8a: // Set second pre-charge speed, color A
assert(len == 2);
break;
case 0x8b: // Set second pre-charge speed, color B
assert(len == 2);
break;
case 0x8c: // Set second pre-charge speed, color C
assert(len == 2);
break;
case 0xa0: // Set driver remap and color depth
assert(len == 2);
m_vaddr_inc = (data[1]&1)?true:false;
// m_fliplr = (data[1]&2)?true:false;
if ((data[1] & 0x0c0)==0)
m_format = OLED_256CLR;
else if ((data[1] & 0x0c0)==0x40)
m_format = OLED_65kCLR;
// else if ((data[1] & 0x0c0)==0x80)
// m_format = OLED_65kCLRTWO;
break;
case 0xa1: // Set display start line register by row
assert(len == 2);
break;
case 0xa2: // Set vertical offset by com
assert(len == 2);
break;
case 0xa4: // Set display mode
case 0xa5: // Fallthrough
case 0xa6: // Fallthrough
case 0xa7: // Fallthrough
assert(len == 1);
break;
case 0xa8: // Set multiplex ratio
assert(len == 2);
break;
case 0xab: // Dim Mode setting
assert(len == 6);
break;
case 0xad:
assert(len == 2);
assert((data[1]&0x0fe)==0x08e);
break;
case 0xac:
case 0xae:
case 0xaf:
assert(len == 1);
break;
case 0xb0: // Power save mode
assert((len == 2)&&((data[1] == 0x1a)||(data[1] == 0x0b)));
break;
case 0xb1: // Phase 1 and 2 period adjustment
assert(len == 2);
break;
case 0xb3: // Displaky clock divider/oscillator frequency
assert(len == 2);
break;
case 0xb8: // Set gray scale table
assert(0 && "Gray scale table not implemented");
break;
case 0xb9: // Enable Linear Gray Scale table
assert(len == 1);
break;
case 0xbb: // Set pre-charge level
assert(len == 2);
break;
case 0xbc: // NOP
case 0xbd: // NOP
assert(len == 1);
case 0xbe: // Set V_COMH
assert(len == 2);
break;
case 0xe3: // NOP
assert(len == 1);
break;
case 0xfd: // Set command lock
assert(len == 2);
if (data[1] == 0x16) {
m_locked = true;
printf("OLED: COMMANDS NOW LOCKED\n");
}
break;
case 0x21: // Draw Line
assert(len == 8);
break;
case 0x22: // Draw Rectangle
assert(len == 11);
break;
case 0x23: // Copy
assert(len == 7);
break;
case 0x24: // Dim Window
assert(len == 5);
break;
case 0x25: // Clear Window
assert(len == 5);
break;
case 0x26: // Fill Enable/Disable
assert(len == 2);
// if (data[0]&1)
// m_drect_fills = 1;
assert((data[1] & 0x10)==0);
break;
case 0x27: // Continuous horizontal and vertical scrolling setup
assert(len == 6);
break;
case 0x2e: // Deactivate scrolling
assert(len == 1);
// m_scrolling = false;
break;
case 0x2f: // Activate scrolling
assert(len == 1);
// m_scrolling = true;
break;
default:
printf("OLED: UNKNOWN COMMAND, data[0] = %02x\n", data[0] & 0x0ff);
assert(0);
break;
}
}
}
 
/*
* set_gddram()
*
* Set graphics display DRAM.
*
* Here is the heart of drawing on the device, or at least pixel level drawing.
* The device allows other types of drawing, such as filling rectangles and
* such. Here, we just handle the setting of pixels.
*
* You'll note that updates to the drawing area are only queued if the device
* is in powered mode.
*
* At some point, I may wish to implement scrolling. If/when that happens,
* the GDDRAM will not be affected, but the area that needs to be redrawn will
* be. Hence this routine will need to be adjusted at that time.
*/
void OLEDSIM::set_gddram(const int col, const int row,
const double dr, const double dg, const double db) {
// Set our color to that given by the rgb (double) parameters.
m_gc->set_source_rgb(dr, dg, db);
 
printf("OLED: Setting pixel[%2d,%2d]\n", col, row);
int drow; // dcol;
drow = row + m_display_start_row;
if (drow >= OLED_HEIGHT)
drow -= OLED_HEIGHT;
m_gc->rectangle(col, row, 1, 1);
m_gc->fill();
 
if (m_state == OLED_POWERED) {
// Need to adjust the invalidated area if scrolling is taking
// place.
double kw, kh;
kw = get_width()/(double)OLED_WIDTH;
kh = get_height()/(double)OLED_HEIGHT;
queue_draw_area(col*kw, row*kh, (int)(kw+0.5), (int)(kh+0.5));
}
}
 
/*
* clear_to()
*
* Clears the simulated device to a known grayscale value. Examples are
* 0.0 for black, or 0.1 for a gray that is nearly black. Note that this
* call does *not* invalidate our window. Perhaps it should, but for now that
* is the responsibility of whatever function calls this function.
*/
void OLEDSIM::clear_to(double v) {
// How do we apply this to our pixmap?
m_gc->set_source_rgb(v, v, v);
m_gc->rectangle(0, 0, OLED_WIDTH, OLED_HEIGHT);
m_gc->fill();
}
 
bool OLEDSIM::on_draw(CONTEXT &gc) {
gc->save();
if (m_state == OLED_POWERED) {
// Scrolling will be implemented here
gc->set_source(m_pix, 0, 0);
gc->scale(get_width()/(double)OLED_WIDTH,
get_height()/(double)OLED_HEIGHT);
gc->paint();
} else {
if ((m_state == OLED_VIO)||(m_state == OLED_RESET))
gc->set_source_rgb(0.1,0.1,0.1); // DARK gray
else
gc->set_source_rgb(0.0,0.0,0.0); // Black
// gc->rectangle(0, 0, OLED_WIDTH, OLED_HEIGHT);
gc->rectangle(0, 0, get_width(), get_height());
gc->fill();
} gc->restore();
 
return true;
}
 
OLEDWIN::OLEDWIN(void) {
m_sim = new OLEDSIM();
m_sim->set_size_request(OLEDSIM::OLED_WIDTH, OLEDSIM::OLED_HEIGHT);
set_border_width(0);
add(*m_sim);
show_all();
Gtk::Window::set_title(Glib::ustring("OLED Simulator"));
}
 
/cpp/oledsim.h
0,0 → 1,128
////////////////////////////////////////////////////////////////////////////////
//
// Filename: oledsim.h
//
// Project: OpenArty, an entirely open SoC based upon the Arty platform
//
// Purpose: To simulate the interaction between the OLED board and my
// logic. This simulator tries to read from the SPI generated
// by the logic, verify that the SPI interaction is valid, and then
// draws the OLED memory to the screen so you can see how the OLED
// would work ... even without having an OLED connected.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#ifndef OLEDSIM_H
#define OLEDSIM_H
 
#include <gtkmm.h>
#include <assert.h>
 
#define OLED_OFF 1
#define OLED_RESET 2
#define OLED_VIO 3
#define OLED_POWERED 4
#define OLED_65kCLR 0
#define OLED_256CLR 1
 
class OLEDSIM : public Gtk::DrawingArea {
public:
typedef Cairo::RefPtr<Cairo::Context> CAIROGC;
typedef const Cairo::RefPtr<Cairo::Context> CONTEXT;
typedef Cairo::RefPtr<Cairo::ImageSurface> CAIROIMG;
 
private:
CAIROIMG m_pix;
CAIROGC m_gc;
 
int m_state, m_reset_clocks; // , m_address_counts;
 
int m_last_csn, m_last_sck, m_last_dcn;
 
int m_idx, m_bitpos;
char m_data[16];
 
bool m_vaddr_inc, m_locked;
int m_format;
int m_col_start, m_col_end, m_col;
int m_row_start, m_row_end, m_row, m_display_start_row;
 
 
void do_command(const int dcn, const int len, char *data);
void handle_io(const int, const int, const int, const int);
void clear_to(const double v);
void set_gddram(const int, const int, const double, const double, const double);
public:
static const int OLED_HEIGHT, OLED_WIDTH;
 
OLEDSIM(void) : Gtk::DrawingArea() {
 
set_has_window(true);
Widget::set_can_focus(false);
set_size_request(OLED_WIDTH, OLED_HEIGHT);
 
m_state = OLED_OFF;
m_locked = true;
m_last_csn = 1;
m_last_sck = 1;
m_last_dcn = 1;
m_format = OLED_65kCLR;
m_display_start_row = 0;
m_vaddr_inc = false;
m_col = 0; m_row = 0;
m_col_start = 0; m_row_start = 0;
m_col_end = 95; m_row_end = 63;
}
 
void get_preferred_width_vfunc(int &min, int &nw) const;
void get_preferred_height_vfunc(int &min, int &nw) const;
void get_preferred_height_for_width_vfunc(int w, int &min, int &nw) const;
void get_preferred_width_for_height_vfunc(int h, int &min, int &nw) const;
 
virtual void on_realize();
virtual bool on_draw(CONTEXT &gc);
void operator()(const int iopwr, const int rstn, const int dpwr,
const int csn, const int sck, const int dcn, const int mosi);
};
 
class OLEDWIN : public Gtk::Window {
private:
OLEDSIM *m_sim;
 
public:
OLEDWIN(void);
~OLEDWIN(void) { delete m_sim; }
void operator()(int iopwr, int rstn, int dpwr,
int sck, int csn, int dcn, int mosi) {
(*m_sim)(iopwr, rstn, dpwr, sck, csn, dcn, mosi);
}
};
 
#endif
/cpp/sdspisim.cpp
378,9 → 378,10
} m_block_buf[0] = 0x0fe;
m_blklen = 512; // (1<<m_csd[5]);
if (m_dev)
fread(&m_block_buf[1], m_blklen, 1, m_dev);
m_blklen = fread(&m_block_buf[1], m_blklen, 1, m_dev);
else
memset(&m_block_buf[1], 0, m_blklen);
m_blklen = (m_blklen != 512) ? 512 : m_blklen;
add_block_crc(m_blklen, m_block_buf);
 
m_blkdly = 60;
/cpp/sdspisim.h
42,6 → 42,8
#ifndef SDSPISIM_H
#define SDSPISIM_H
 
#include <stdio.h>
 
typedef enum eRESET_STATES {
SDSPI_POWERUP_RESET,
SDSPI_CMD0_IDLE,

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.