diff --git a/MK404.cpp b/MK404.cpp index 120a584c..7642f00f 100644 --- a/MK404.cpp +++ b/MK404.cpp @@ -362,7 +362,7 @@ int main(int argc, char *argv[]) // Longer term it'd be neat to have a synonym handler in TCLAP.... bool bArgHacks = argNoHacks.isSet() || argKlipper.isSet() || argMarlin.isSet(); bool bArgSkew = argSkew.isSet() || argKlipper.isSet(); - + Config::Get().SetSkewCorrect(bArgSkew); // Make new image. if (argImgSize.isSet()) { diff --git a/parts/Board.cpp b/parts/Board.cpp index 1c064e43..a4a1079c 100644 --- a/parts/Board.cpp +++ b/parts/Board.cpp @@ -404,23 +404,76 @@ namespace Boards { void* Board::RunAVR() { + // std::vector vdC, vsim; + // std::vector vwall; + // vdC.reserve(10000); + // vwall.reserve(10000); + // vsim.reserve(10000); + // Idle lambda that stops the virtual AVR calling usleep. + auto fcnSleep = [](avr_t*, avr_cycle_count_t) { return; }; avr_regbit_t MCUSR = m_pAVR->reset_flags.porf; MCUSR.mask =0xFF; MCUSR.bit = 0; std::cout << "Starting " << m_wiring.GetMCUName() << " execution...\n"; + struct timespec tp {0,0}, tStart {0,0}; + clock_gettime(CLOCK_MONOTONIC, &tStart); + volatile uint64_t idle = 1000000; + while (idle>0) + { + asm(""); // NOLINT - is what it is so that it doesn't get optimized out. + idle--; + } + clock_gettime(CLOCK_MONOTONIC, &tp); + uint64_t idlens = tp.tv_nsec - tStart.tv_nsec; + auto fnsPerIdle = static_cast(idlens)/1e6f; + std::cout << "10M idle cycles is " << std::to_string(idlens) << " ns (" << std::to_string(fnsPerIdle) << " ns per tick)\n"; + if (m_bCorrectSkew) + { + m_pAVR->sleep = fcnSleep; + } int state = cpu_Running; + auto tNext = m_pAVR->cycle; + uint64_t uiIdle = 10000, uiLost = 0; while ((state != cpu_Done) && (state != cpu_Crashed) && !m_bQuit){ // Check the timing every 10k cycles, ~10 ms - if (m_bCorrectSkew && m_pAVR->cycle%500==0) + if (m_bCorrectSkew && m_pAVR->cycle>tNext) { auto tWall = avr_get_time_stamp(m_pAVR); - auto tSim = avr_cycles_to_nsec(m_pAVR, m_pAVR->cycle); + auto tSim = avr_cycles_to_nsec(m_pAVR, m_pAVR->cycle) + uiLost; if (tWall200000) usleep(tDiff/1000); - //std::cout << "Sim is ahead by" << std::to_string(tSim - tWall) << "ns!\n"; + auto tDiff = gsl::narrow(tSim - static_cast(tWall)); + if (tDiff>100000) + { + uint64_t volatile idle = (static_cast(tDiff)/fnsPerIdle); + while (idle>0) + { + asm(""); // NOLINT - is what it is so that it doesn't get optimized out. + idle--; + } + // auto tSleep = gsl::narrow(avr_get_time_stamp(m_pAVR) - tWall); + // if (tSleep > tDiff+150000) std::cout << "Slept too long! Asked: " << std::to_string(tDiff/1000) << " got " << std::to_string(tSleep/1000) << "us!\n"; + } + } + if (tSim(static_cast(tWall)-tSim); + if (tDiff>1000000) // 1 ms + { + std::cout << "Lost " << std::to_string(tDiff/1000) << " us!\n"; + if (tDiff>5000000) // If we lose more than 5ms, don't try to catch up. + { + uiLost += tDiff; + } + } } + // if (vsim.size()<10000) + // { + // vwall.push_back(tWall); + // vsim.push_back(tSim); + // vdC.push_back(m_pAVR->cycle); + // } + tNext = m_pAVR->cycle + uiIdle; } if (m_bIsPrimary) // Only one board should be scripting. { @@ -457,6 +510,12 @@ namespace Boards { } std::cout << m_wiring.GetMCUName() << "finished (" << state << ").\n"; avr_terminate(m_pAVR); + // std::cout << "cycles, wall, sim\n"; + // for (size_t i=0; i lock(m_lock); for (auto &c : m_vRam) { c = ' '; @@ -102,7 +101,7 @@ Scriptable::LineStatus HD44780::ProcessAction(unsigned int iAction, const std::v { return IssueLineError(std::string("ADDR") + std::to_string(iAddr) + " is out of range [0,63]"); } - if (m_cgRam[iAddr] == stoi(vArgs.at(0))) + if (gsl::at(m_cgRam,iAddr) == stoi(vArgs.at(0))) { return LineStatus::Finished; } @@ -218,16 +217,14 @@ uint32_t HD44780::OnDataReady() uint32_t delay = 37; // uS if (m_bInCGRAM) { - std::lock_guard lock(m_lock); - m_cgRam[m_uiCGCursor] = m_uiDataPins; + gsl::at(m_cgRam,m_uiCGCursor) = m_uiDataPins; TRACE(printf("hd44780_write_data %02x to CGRAM %02x\n",m_uiDataPins,m_uiCGCursor)); IncrementCGRAMCursor(); } else { { - std::lock_guard lock(m_lock); - m_vRam[m_uiCursor] = m_uiDataPins; + m_vRam.at(m_uiCursor) = m_uiDataPins; } for (unsigned int i=0; i lock(m_lock); - m_uiReadPins = m_vRam[m_uiCursor]; + m_uiReadPins = gsl::at(m_vRam,m_uiCursor); } IncrementCursor(); } else { // read 'command' ie status register diff --git a/parts/components/HD44780.h b/parts/components/HD44780.h index 27ce5622..448744ff 100644 --- a/parts/components/HD44780.h +++ b/parts/components/HD44780.h @@ -59,7 +59,6 @@ #include "sim_irq.h" // for avr_irq_t #include #include // for uint8_t, uint16_t, uint32_t -#include #include // for string #include // for vector @@ -100,10 +99,8 @@ class HD44780:public BasePeripheral, public Scriptable // The GL draw accesses these: std::atomic_uint8_t m_uiHeight = {4}; // width and height of the LCD std::atomic_uint8_t m_uiWidth = {20}; - uint8_t _m_vRam[104] {' '}; - uint8_t _m_cgRam[64] {' '}; - gsl::span m_vRam {_m_vRam}; - gsl::span m_cgRam {_m_cgRam}; + std::array m_vRam = {}; + std::array m_cgRam = {}; LineStatus ProcessAction(unsigned int iAction, const std::vector &args) override; @@ -149,8 +146,6 @@ class HD44780:public BasePeripheral, public Scriptable std::vector m_lineOffsets = {0, 0x40, 0, 0x40}; - std::mutex m_lock; // Needed for GL thread access to v/cgRAM - private: enum Actions { diff --git a/parts/components/HD44780GL.cpp b/parts/components/HD44780GL.cpp index ba730612..b425483b 100644 --- a/parts/components/HD44780GL.cpp +++ b/parts/components/HD44780GL.cpp @@ -42,7 +42,6 @@ #else # include // for glVertex3f, glBegin, glEnd, glMaterialfv #endif -#include #include //#define TRACE(_w) _w @@ -146,6 +145,8 @@ void HD44780GL::GenerateCharQuads() void HD44780GL::GLPutChar(unsigned char c, uint32_t character, uint32_t text, uint32_t shadow, bool bMaterial) { + uint8_t _cgChar[8]; + gsl::span pChar {_cgChar}; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColorHelper(character,bMaterial); @@ -158,7 +159,11 @@ void HD44780GL::GLPutChar(unsigned char c, uint32_t character, uint32_t text, ui uint8_t iCols=8; if (c<16) { - uiData = m_cgRam.begin() + ((c & 7U) <<3U); + for (int i=0; i lock(m_lock); - GLPutChar(m_vRam[m_lineOffsets.at(v) + i], character, text, shadow, bMaterial); + GLPutChar(gsl::at(m_vRam,m_lineOffsets.at(v) + i), character, text, shadow, bMaterial); glTranslatef(6, 0, 0); } glPopMatrix(); diff --git a/parts/components/uart_pty.cpp b/parts/components/uart_pty.cpp index d823045a..bd42b4ef 100644 --- a/parts/components/uart_pty.cpp +++ b/parts/components/uart_pty.cpp @@ -23,6 +23,7 @@ #include "uart_pty.h" +#include "Config.h" #include "avr_uart.h" // for AVR_IOCTL_UART_GETIRQ, ::AVR_... #include "gsl-lite.hpp" #include "sim_io.h" // for avr_io_getirq, avr_ioctl @@ -331,6 +332,10 @@ void uart_pty::Connect(char uart) uint32_t f = 0; avr_ioctl(m_pAVR, AVR_IOCTL_UART_GET_FLAGS(uart), &f); //NOLINT - complaint in external macro f &= ~AVR_UART_FLAG_STDIO; + if (Config::Get().GetSkewCorrect()) + { + f&= ~(AVR_UART_FLAG_POLL_SLEEP); + } avr_ioctl(m_pAVR, AVR_IOCTL_UART_SET_FLAGS(uart), &f); //NOLINT - complaint in external macro avr_irq_t * src = avr_io_getirq(m_pAVR, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUTPUT); //NOLINT - complaint in external macro diff --git a/utility/Config.h b/utility/Config.h index 4e1caf43..8ad62e28 100644 --- a/utility/Config.h +++ b/utility/Config.h @@ -40,8 +40,13 @@ class Config inline void SetColourE(bool bVal){ m_bColorExtrusion = bVal;} inline bool GetColourE(){ return m_bColorExtrusion;} + // Should extrusion be coloured by width?. + inline void SetSkewCorrect(bool bVal){ m_bSkew = bVal;} + inline bool GetSkewCorrect(){ return m_bSkew;} + private: unsigned int m_iExtrusion = false; bool m_bColorExtrusion = false; + bool m_bSkew = false; };