profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/michaelfranzl/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.

michaelfranzl/no.php 101

Transparent reverse proxy written in PHP

jasonknight/salor-retail 77

Rails Based Point of Sale and Store Management Software

michaelfranzl/escper 67

Ruby gem for printing of images and text on one or many thermal printers

michaelfranzl/janus-rtpforward-plugin 62

Plugin for Janus forwarding RTP and RTCP packets to an external UDP receiver/decoder, e.g. a GStreamer pipeline

jasonknight/woocommerce-json-api 59

A simple, Abstract JSON API for Wordpress' Awesome Plugin: WooCommerce

michaelfranzl/minnie-janus 28

Small, ES8, isomorphic library for interfacing with the Janus WebRTC gateway.

michaelfranzl/docx_converter 26

Ruby gem converting Word docx files into html or LaTeX via the Kramdown syntax

michaelfranzl/gerbil 16

Universal and reusable Grbl CNC firmware interface module for Python3

michaelfranzl/gerbil_gui 16

Gcode scripting, 3D visualization and streaming for the grbl CNC controller

michaelfranzl/pyglpainter 13

Python OpenGL Painter - Minimalistic but modern OpenGL drawing for technical applications

issue openedTalentBox/sequel-rails

Configurable debug level

The log level is hard-coded to debug:

https://github.com/TalentBox/sequel-rails/blob/db6778f1fbdc15a4a53f9f406dc6354debdd17fb/lib/sequel_rails/railties/log_subscriber.rb#L56

Can the logger method be made configurable?

created time in a day

push eventmichaelfranzl/virtualagc

Michael K. Franzl

commit sha d32edbe257b30b23c82b177f02f78d43028693fc

yaAGC: Output all channel updates during initialization

view details

push time in 2 days

push eventmichaelfranzl/virtualagc

Mike Stewart

commit sha b89dfc6228043faa1c710798648b6188ede8b1c4

yaAGC: Big refactor for improved scaler logic and cycle-accurate counter simulation.

view details

Mike Stewart

commit sha ef41eb37317fa9e66ccf0e7946f9a3e7277e96ab

yaAGC: Added full simulation of the RHC counters

view details

Mike Stewart

commit sha ad7b6cb10192c5c22a5f10e9a90963142a1271bd

yaAGC: Added simulation of the radar interface

view details

Mike Stewart

commit sha 02cd3bf73d32d9f11dd137aff44bfabb157b0c7a

yaAGC: Added simulation of the GYROCMD output counter

view details

Mike Stewart

commit sha 7b6215593c9c5a7cf0b06fdc16bfec8365ee434b

yaAGC: Added simulation of the five CDU drive counters

view details

Mike Stewart

commit sha 1dec1bc683aefc5700f14f9814cfac1468b8718b

yaAGC: Added simulation of THRUST and EMSD counters

view details

Mike Stewart

commit sha 4c1c52ea3b824368f94a22cccfde4401a5c7b2e5

yaAGC: Added simulation of the OUTLINK and ALTM output counters

view details

Mike Stewart

commit sha 665b571e21d50f1376c229dc3721f7f9e2435b07

yaAGC: Added a skeleton PulseOutput() function and changed output counters to use it

view details

Mike Stewart

commit sha 133175b27159d5b44394b42a59b896d2e4ebf3d5

yaAGC: Added a PulseInput(), which handles logic for incoming pulses to the AGC. PIPAs and uplink/crosslink are now fully simulated.

view details

Mike Stewart

commit sha 35a91d533ecfe2fbf1cb39024413275ed1c3b7f8

yaAGC: Integrated the LR and RR into the new PulseInput/PulseOutput interface

view details

Michael K. Franzl

commit sha 8d7be20dd7a03f5bffbd485cd81d43972432d1aa

yaAGC: Remove unused return value of ChannelInput

view details

Michael K. Franzl

commit sha 6a3416e93aef015994d7d0d4fae824fddaf06903

yaAGC: Fix typos

view details

Michael K. Franzl

commit sha a09ff1bc5ed498d5f6f45b779307d3a0f10bdc9a

yaAGC: Add all missing ChannelOutput calls after channel updates

view details

Michael K. Franzl

commit sha 80917be5041acd6777797fff2903e133529265d9

yaAGC: Refactoring: Remove redundant state modification This is already done in CpuWriteIO.

view details

Michael K. Franzl

commit sha 77e3312a45951839f285ab981885aa285b952a33

yaAGC: Output all channel updates during initialization

view details

push time in 2 days

issue closedmichaelfranzl/janus-rtpforward-plugin

Jitter handling

Hi @michaelfranzl thanks for this plugin. I've got a question, do you have an idea of how to handle a jitter on video stream on the receiver side? What I want to understand If sender got a bad connection, how to handle packet losses. Thank you in advance.

closed time in 4 days

B-R-Bender

issue commentmichaelfranzl/janus-rtpforward-plugin

Jitter handling

The plugin is a simple forwarder; it doesn't even know about jitter or lost packets. It seems to me you need to direct that question elsewhere.

B-R-Bender

comment created time in 4 days

issue closedmichaelfranzl/no.php

Support for multiple domains

Can we add 2 or more domains as backend ?

closed time in 4 days

pereceh

issue commentmichaelfranzl/no.php

Support for multiple domains

No.

pereceh

comment created time in 4 days

startedtmux-plugins/tmux-resurrect

started time in 5 days

startedtpope/vim-obsession

started time in 5 days

push eventmichaelfranzl/virtualagc

Michael K. Franzl

commit sha 45a849b1faf2dda0f724d47586746a802a3c3e38

fixup! yaAGC: Added simulation of the radar interface

view details

Michael K. Franzl

commit sha 3f0e44da4a9711385cbdbe5629bfcb1bce99cd59

fixup! yaAGC: Big refactor for improved scaler logic and cycle-accurate counter simulation.

view details

Michael K. Franzl

commit sha 41a474c3ff149ab6628600882e3cded1851a6cc9

fixup! yaAGC: Added simulation of the five CDU drive counters

view details

Michael K. Franzl

commit sha 8745ae43410a4357ed01145a5f4b6b44d1f9a226

fixup! yaAGC: Added simulation of the five CDU drive counters

view details

Michael K. Franzl

commit sha 23f618232d0a3b44708f1912da89f9377ad5af86

fixup! yaAGC: Big refactor for improved scaler logic and cycle-accurate counter simulation.

view details

Michael K. Franzl

commit sha f855116f39212873586b41cf5e8079fd6bace284

Add all missing ChannelOutput calls after channel updates

view details

Michael K. Franzl

commit sha 934032b2bf6ede17a20b0a3d6f152aa3a53ca8fa

Refactoring: Remove redundant state modification This is already done elsewhere

view details

Michael K. Franzl

commit sha 3a0dec5665930e5902ebcf91946ba8b8580c88a2

Refactoring: Output channel 077 state only when 077 is modified

view details

Michael K. Franzl

commit sha 340b24ba47997fc80a23adeb2944eebd9255fab3

Remove irrelevant ChannelMask from Ringbuffer API

view details

push time in 6 days

push eventmichaelfranzl/virtualagc

Michael K. Franzl

commit sha 8cd724c8e7ef34cebd1e6ac69004b318c4410348

Add all missing ChannelOutput calls after channel updates

view details

Michael K. Franzl

commit sha 787dae1d4e66b2a3d15001eb15a9344d7d547e84

Refactoring: Remove redundant state modification This is already done elsewhere

view details

Michael K. Franzl

commit sha 6c29c691173660f9a076a3ae190040a84bcec049

Refactoring: Output channel 077 state only when 077 is modified

view details

Michael K. Franzl

commit sha eab4db8432eedb76393b4e5081d0f270e1b4c598

Remove irrelevant ChannelMask from Ringbuffer API

view details

push time in 6 days

push eventmichaelfranzl/webAGC

Michael K. Franzl

commit sha b68554a1df9e4c22810ccfe9097bd410da1bca0c

Demo: Add channel number headings

view details

Michael K. Franzl

commit sha aec12e7b3e5f4775becc79b03ad15b476bce40dc

Demo: Highlight registers

view details

Michael K. Franzl

commit sha 1b721471960f64d5f43ce16174fc2cdc448506de

More precision for the MCT cycle time

view details

Michael K. Franzl

commit sha ed6412707c5c171d269bc8b008032aced475c57c

Demo: Upgrade to webdsky 1.1.3

view details

Michael K. Franzl

commit sha fe0497b8b90e07f777d8bf9522dbb3889307d3ff

Demo: Optimize loading

view details

Michael K. Franzl

commit sha 79dc8c8190e74bb46bb5c0a05018b54796033e94

Demo: More precision for AGC cycle time display

view details

Michael K. Franzl

commit sha e72d84d09e3314c09c79a9aa78926325d497683a

Demo: Allow manipulation of output channels

view details

Michael K. Franzl

commit sha 16b48adaf35b5351346c3b9674591dc910dfd73b

More precise and simpler AGC stepping

view details

Michael K. Franzl

commit sha f932de0203eee8ca0e282ae1681c59d3af052223

Remove unnecessary channel bitmask configuration webAGC is the only interface to yaAGC and so will always have full knowledge of the channel states

view details

Michael K. Franzl

commit sha d5e5f2077ccc0a07b2d1b8401f59a626c83de014

Demo: Change channel labels

view details

Michael K. Franzl

commit sha 73b595678ff7e8586a3e021b65fe3e00b49737c7

Demo: Add simulation elapsed time clock

view details

Michael K. Franzl

commit sha 2b2728b263000f4532d0b31a331213b4887a42bf

Demo: Add convenience functions to AGCChannel

view details

Michael K. Franzl

commit sha 2ec5141d7385e645b67d8926d5a69fa139c6b5af

Demo: Stop using keypress functions of webAGC

view details

Michael K. Franzl

commit sha 2b8341c3da1c3fb3e3a8c7c6885ed03ea2705212

Delete keypress functions

view details

Michael K. Franzl

commit sha 106296d4e6f2acc9dd59a153d48a887756ca1f58

Add a warning about ringbuffer capacity

view details

Michael K. Franzl

commit sha 553c93d2e22debf6f8f5866a6c7cc86b56b84be0

Make readAllIo private

view details

Michael K. Franzl

commit sha bb465b1f8923d875f1d7ba9bdc53dcbc00e5ec69

Demo: Refactoring

view details

Michael K. Franzl

commit sha 5982972e3a254d179750e7330fc67aef79bdb677

Demo: Set sane initial input channel state

view details

Michael K. Franzl

commit sha 7526413d255a090cdf61985816faaa45295048fd

Demo: Remove unnecessary state bypass

view details

Michael K. Franzl

commit sha 9450436f63a492c3aef21157a22f4201754378fb

Demo: Quicker DSKY auto-typing

view details

push time in 6 days

startedInvoca/magic_frozen_string_literal

started time in 9 days

startedyuttie/comfortable-motion.vim

started time in 10 days

startedfaker-ruby/faker

started time in 11 days

Pull request review commentvirtualagc/virtualagc

Improved scaler logic and counter simulation for yaAGC

 SimulateDV(agc_t *State, uint16_t divisor)     uint16_t l = c(RegL);     int i; -    // Assume A contains the sign of the dividend-    dividend_sign = a & 0100000;+    // Assume A contains the sign of the dividend+    dividend_sign = a & 0100000;++    // Negate A if it was positive+    if (!dividend_sign)+      a = ~a;+    // If A is now -0, take the dividend sign from L+    if (a == 0177777)+      dividend_sign = l & 0100000;+    // Negate L if the dividend is negative.+    if (dividend_sign)+      l = ~l;++    // Add 40000 to L+    l = AddSP16(l, 040000);+    // If this did not cause positive overflow, add one to A+    if (ValueOverflowed(l) != AGC_P1)+      a = AddSP16(a, 1);+    // Initialize the remainder with the current value of A+    remainder = a;++    // Record the sign of the divisor, and then take its absolute value+    divisor_sign = divisor & 0100000;+    if (divisor_sign)+      divisor = ~divisor;+    // Initialize the quotient via a WYD on L (L's sign is placed in bits+    // 16 and 1, and L bits 14-1 are placed in bits 15-2).+    quotient_sign = l & 0100000;+    quotient = quotient_sign | ((l & 037777) << 1) | (quotient_sign >> 15);++    for (i = 0; i < 14; i++)+    {+        // Shift up the quotient+        quotient <<= 1;+        // Perform a WYD on the remainder+        remainder_sign = remainder & 0100000;+        remainder = remainder_sign | ((remainder & 037777) << 1);+        // The sign is only placed in bit 1 if the quotient's new bit 16 is 1+        if ((quotient & 0100000) == 0)+          remainder |= (remainder_sign >> 15);+        // Add the divisor to the remainder+        sum = AddSP16(remainder, divisor);+        if (sum & 0100000)+          {+            // If the resulting sum has its bit 16 set, OR a 1 onto the+            // quotient and take the sum as the new remainder+            quotient |= 1;+            remainder = sum;+          }+    }+    // Restore the proper quotient sign+    a = quotient_sign | (quotient & 077777);++    // The final value for A is negated if the dividend sign and the+    // divisor sign did not match+    c(RegA) = (dividend_sign != divisor_sign) ? ~a : a;+    // The final value for L is negated if the dividend was negative+    c(RegL) = (dividend_sign) ? remainder : ~remainder;+}++//-----------------------------------------------------------------------------+// These functions implement scaler timing logic. The scaler is a 33-stage+// binary counter whose outputs are used to time many things throughout the+// AGC. Each stage has four outputs -- the inverted and noninverted state for+// that stage (named, eg., FS09 and FS09/), and two timing pulses of the form+// FxxA and FxxB. Timing pulse FxxA is emitted when the stage transitions from+// a 1 to a 0, and timing pulse FxxB is emitted when the stage transitions+// from a 0 to a 1. The frequency of each stage can be calculated by the+// forumula (1.024 kHz)/(2^x), where x is the number of the stage.+//+// Our implementation of the scaler omits stages 1 and 2, since they are too+// fast and time things too finely detailed for an emulator to care about.+// We simply advance our scaler counter once at the beginning of every MCT,+// and if that causes stage 3 to increment, we generate all expected+// timing pulses.++// Timepulse F03B generates PIPA data strobes, causing all three to generate+// either a plus or a minus count request. This happens only when FS04 is+// set and FS05 isn't -- i.e, every fourth F03B.+static void+TimingSignalF03B(agc_t * State)+{+    if ((State->ScalerValue & (SCALER_FS05 | SCALER_FS04)) == SCALER_FS04)+      PulseOutput(State, OUTPUT_PIPA_DATA);+}++// Timepulse F04A clears the uplink-too-fast bit, which is set by each+// incoming uplink bit. If another uplink bit arrives before F04A occurs,+// the new bit will be dropped and the computer will be notified via+// channel 33 bit 11.+static void+TimingSignalF04A(agc_t * State)+{+    State->UplinkTooFast = 0;+}++// Timepulse F05A is far and away the busiest timing signal. It is used +// for some standby-powered circuitry that monitors voltage levels. We +// are not simulating power supply failures, and the input voltage must+// go well below its lower limit for the AGC power supply outputs to+// dip, so we only monitor the input voltage.+// +// It checks inputs for the three input traps (31A, 31B, and 32) and+// sets a bit for each if they are active. If F05B occurs before a+// triggered trap gets reset, a HANDRUPT will be generated.+//+// This timepulse also generates many output count requests: the BMAG/RHC+// and RNRAD input counters, and all output counters use this timepulse.+static int+TimingSignalF05A(agc_t * State)+{+    int CausedRestart = 0;+    int i = 0;+    int PulseType = 0;++    // First, perform standby-powered stuff. Has our input voltage+    // remained below the limit since F05B?+    if (State->InputVoltageLow)+    {+        // The input voltage is bad. If we're in standby, this generates+        // an input to the warning filter.+        if (State->Standby)+            State->GeneratedWarning = 1;++        if (!InhibitAlarms)+        {+            // If the alarm isn't disabled, the computer will be held in+            // restart (via signal STRT1) until the next F05A in which the+            // the voltage is back within limits. Trigger a GOJAM and set+            // the appropriate CH77 bit.+            State->RestartHold = 1;+            State->InputChannel[077] |= CH77_VOLTAGE_FAIL;+            CausedRestart = 1;+        }+    }+    else+    {+        // Voltage is good, so de-assert the STRT1 restart hold+        State->RestartHold = 0;+    }++    // That's it for standby-powered stuff, so leave if we're in standby+    if (State->Standby)+        return CausedRestart;++    // Set the PIPA pulse missing monitoring bits for each PIPA+    State->PipaMissX = 1;+    State->PipaMissY = 1;+    State->PipaMissZ = 1;++    // Check for any of the input traps to be triggered. If they are, and+    // the cause of the triggering doesn't go away before F05B, we'll+    // generate a HANDRUPT.+    if (State->Trap31A && ((State->InputChannel[031] & 000077) != 000077))+        State->Trap31APending = 1;++    if (State->Trap31B && ((State->InputChannel[031] & 007700) != 007700))+        State->Trap31BPending = 1;++    if (State->Trap32 && ((State->InputChannel[032] & 001777) != 001777))+        State->Trap32Pending = 1;++    // Check for RHC input pulses+    for (i = 0; i < 3; i++)+    {+        if (State->RHCCounts[i] > 0)+        {+            State->RHCCounts[i]--;+            if (State->InputChannel[013] & 0200)+                CounterRequest(State, COUNTER_RHCP + i, COUNTER_CELL_PLUS);+        }+        else if (State->RHCCounts[i] < 0)+        {+            State->RHCCounts[i]++;+            if (State->InputChannel[013] & 0200)+                CounterRequest(State, COUNTER_RHCP + i, COUNTER_CELL_MINUS);+        }+    }++    // Generate radar count requests if a valid radar is selected+    if (State->RadarSync)+    {+        if (State->InputChannel[013] & 04)+            PulseOutput(State, OUTPUT_LR_SYNC);+        else if ((State->InputChannel[013] & 03) != 0)+            PulseOutput(State, OUTPUT_RR_SYNC);+    }++    // Generate gyro drive pulses+    if (State->InputChannel[014] & 01000)+    {+        // At least one DINC is always generated regardless of the value+        // in the GYROCMD counter. The result of that DINC will determine+        // what happens next; if it generates a ZOUT, the drive active bit+        // and channel 14 bit 10 are cleared. Otherwise, the active bit is+        // set, which allows these F05A timing signals to generate drive+        // pulses to the gyros.+        CounterRequest(State, COUNTER_GYROCMD, COUNTER_CELL_PLUS);+        if (State->GyroDriveActive)+          PulseOutput(State, OUTPUT_GYROCMD_SET);+    }+    else+        State->GyroDriveActive = 0;++    // Generate CDU drive pulses if their respective channel 14 bits are+    // set. The output pulses themselves are generated during the DINC,+    // with a ZOUT resetting the channel 14 bit to disable the counter.+    if (State->InputChannel[014] & 040000)+      CounterRequest(State, COUNTER_CDUXCMD, COUNTER_CELL_PLUS);+    if (State->InputChannel[014] & 020000)+      CounterRequest(State, COUNTER_CDUYCMD, COUNTER_CELL_PLUS);+    if (State->InputChannel[014] & 010000)+      CounterRequest(State, COUNTER_CDUZCMD, COUNTER_CELL_PLUS);+    if (State->InputChannel[014] & 04000)+      CounterRequest(State, COUNTER_OPTYCMD, COUNTER_CELL_PLUS);+    if (State->InputChannel[014] & 02000)+      CounterRequest(State, COUNTER_OPTXCMD, COUNTER_CELL_PLUS);++    // THRUST and EMSD operate identically, with THRUST being enabled by+    // channel 14 bit 4, and EMSD being enabled by bit 5. For these,+    // F05A is responsible for both generating DINC requests *and*+    // sending the resulting output pulses. A POUT or a MOUT on the+    // first DINC will set a bit that allows plus or minus pulses,+    // respectively, on subsequent F05As. These bits are never cleared+    // until the CH14 enable bits are cleared, so if the value in the+    // counter changes sign for some reason, both plus and minus output+    // pulses will be generated until the counter is disabled.+    if (State->InputChannel[014] & 010)+    {+        if (State->ThrustPlusActive)+          PulseOutput(State, OUTPUT_THRUST_PLUS);+        if (State->ThrustMinusActive)+          PulseOutput(State, OUTPUT_THRUST_MINUS);++        CounterRequest(State, COUNTER_THRUST, COUNTER_CELL_PLUS);+    }++    if (State->InputChannel[014] & 020)+    {+        if (State->EMSPlusActive)+          PulseOutput(State, OUTPUT_EMSD_PLUS);+        if (State->EMSMinusActive)+          PulseOutput(State, OUTPUT_EMSD_MINUS);++        CounterRequest(State, COUNTER_EMSD, COUNTER_CELL_PLUS);+    }++    // OUTLINK and ALTM are also almost identical. OUTLINK is enabled+    // by channel 14 bit 1. After this bit is set to 1, nothing happens+    // until the following GTSET, which sets up the output circuitry.+    // The first F05A after this GTSET, a "1" output pulse is generated+    // as a sync marker. This F05A will also generate a SHINC request,+    // as will every subsequent F05A until the outlink counter is+    // disabled by another GTSET. +    //+    // The first F05A of an outlink will also clear the enable flip-flop,+    // channel 14 bit 1. However, this bit will still read as 1 to+    // software, because for reading its state is ORed together with+    // the "outlink active" flip-flop.+    //+    // ALTM behaves almost identically. It is enabled by channel 14 bit+    // 3. It can target one of two pairs of output pins; altitude if+    // channel 14 bit 2 is 0, and altitude rate if it is 1. This+    // selection is "checked" with every output pulse, so misbehaving+    // software can change which interface is being addressed in the+    // middle of an output cycle.+    if (State->OutlinkActive)+    {+        if (State->OutlinkStarting)+        {+            State->OutlinkStarting = 0;+            PulseOutput(State, OUTPUT_OUTLINK_ONE);+            State->InputChannel[014] &= ~01;+        }+        else+          CounterRequest(State, COUNTER_OUTLINK, COUNTER_CELL_ZERO);+    }++    if (State->AltActive)+    {+        if (State->AltStarting)+        {+            State->AltStarting = 0;+            State->InputChannel[014] &= ~04;+            if (State->InputChannel[014] & 02)+              PulseOutput(State, OUTPUT_ALTRATE_ONE);+            else+              PulseOutput(State, OUTPUT_ALT_ONE);+        }+        else+          CounterRequest(State, COUNTER_ALTM, COUNTER_CELL_ZERO);+    }++    return CausedRestart;+}++// Timepulse F05B checks to see if any voltage sources are out of limits,+// and if they are, notes it down. If the problem hasn't been resolved+// by F05A, we'll generate an alarm. It also generates HANDRUPTs if any+// of the input traps are enabled and triggered.+// Timing pulses GTSET, GTRST, and GTONE are potentially generated,+// depending on the state of scaler stages 6-9. These pulses are used+// by the radar, outlink, and altimeter interfaces.+static void+TimingSignalF05B(agc_t * State)+{+    unsigned GtsetType;+    // If the input voltage is below the voltage fail circuit threshold,+    // set a bit for F05A to check.+    if (State->InputVoltagemV < VFAIL_THRESHOLD)+        State->InputVoltageLow = 1;++    if (State->Standby)+        return;++    // Set the PIPA fail bit if any expected PIPA pulses were not received+    if (State->PipaMissX || State->PipaMissY || State->PipaMissZ)+      State->InputChannel[033] &= ~010000;++    // If any of the input traps are pending, generate a HANDRUPT and+    // disable the tripped trap.+    if (State->Trap31APending)+    {+        State->Trap31A = 0;+        State->Trap31APending = 0;+        State->InterruptRequests[RUPT_HANDRUPT] = 1;+    }++    if (State->Trap31BPending)+    {+        State->Trap31B = 0;+        State->Trap31BPending = 0;+        State->InterruptRequests[RUPT_HANDRUPT] = 1;+    }++    if (State->Trap32Pending)+    {+        State->Trap32 = 0;+        State->Trap32Pending = 0;+        State->InterruptRequests[RUPT_HANDRUPT] = 1;+    }++    // Handled GTSET, GTRST, and GTON-driven logic+    GtsetType = State->ScalerValue & SCALER_GTSET;+    if (GtsetType == SCALER_GTSET)+    {+        // If the radar gate counter has reached 9, begin generating sync+        // pulses and getting count requests back.+        if (State->RadarGateCounter == 9)+          State->RadarSync = 1;++        // Outlink and tape meter outputs function identically; GTSET will+        // begin an outgoing pulse sequence if there is not one already+        // active, otherwise it will end the ongoing one and clear the+        // channel enable bit.+        if (State->OutlinkActive)+        {+            State->InputChannel[014] &= ~01;+            State->OutlinkActive = 0;+        }+        else if (State->InputChannel[014] & 01)+        {+            State->OutlinkActive = 1;+            State->OutlinkStarting = 1;+        }++        if (State->AltActive)+        {+            State->InputChannel[014] &= ~04;+            State->AltActive = 0;+        }+        else if (State->InputChannel[014] & 04)+        {+            State->AltActive = 1;+            State->AltStarting = 1;+        }+    }+    else if (GtsetType == SCALER_GTRST)+    {+        // If a radar sync was active, stop it, generate a RADARUPT, and+        // reset all of the related state information+        if (State->RadarSync)+        {+            State->InterruptRequests[RUPT_RADARUPT] = 1;+            State->InputChannel[013] &= ~010;

Thanks for the hint! This is OK for me. :) I'm making suggestions specific to the changes in this branch independent from it being merged, with the intent of making the code slightly more adapted for the integration in peripheral simulations.

As this does create some clutter in the comment section of this pull request, maybe it is better to simply modify my fork of this branch. My changes could then be contributed later.

For what it's worth, the conflicts in this pull request are located only in the comment preambles of a few files and can be easily resolved. My fork of this branch is already rebased on an up-to-date main branch.

thewonderidiot

comment created time in 12 days

PullRequestReviewEvent

push eventmichaelfranzl/virtualagc

nobody

commit sha 5b789f53f9ead0825042742569aa139bb7b94fcf

fixup! yaAGC: Added simulation of the radar interface

view details

Michael K. Franzl

commit sha b1cb161ddcfe89702459796a512151d5b89fedeb

fixup! yaAGC: Big refactor for improved scaler logic and cycle-accurate counter simulation.

view details

nobody

commit sha c095f27171fc411602144d931a8797e5c8cd8115

fixup! yaAGC: Added simulation of the five CDU drive counters

view details

nobody

commit sha d73f4c2b192ba2a593f4bf256655bf635be2f2cf

fixup! yaAGC: Added simulation of the five CDU drive counters

view details

Michael K. Franzl

commit sha 1701aab0feabd74782c026bce2e3c5329c0d3929

fixup! yaAGC: Big refactor for improved scaler logic and cycle-accurate counter simulation.

view details

push time in 12 days

push eventmichaelfranzl/virtualagc

Thymo van Beers

commit sha ff4d9e79360d3842ae354b47caf09cc6bd37e7d7

Added --no-resume cli option

view details

Ronald Burkey

commit sha 1bd6f8fffc28ad42d0462934ed928cf7ef090edd

Merge pull request #1148 from ThymoNL/no-resume Added --no-resume cli option

view details

Mike Stewart

commit sha db489ea61cdffc75329f266f39930b9c6b46619d

yaAGCb1: Fixed a few errors identified by SELF-CHECK

view details

Mike Stewart

commit sha fd07c5b8170141de2ae8115ba2f61464f91acb8d

yaAGCb1: Retain the contents of A on TS A with overflow

view details

Mike Stewart

commit sha 9587743958db3c7f6dcf9cf4771d21dc3ef86468

yaAGCb1: Corrections to CCS and SU, which fully fix RUPTCHK

view details

Mike Stewart

commit sha feabfcc6514f3fb411605a6982bc539a220b8fe6

yaAGCb1: Corrected SL and division of equal-magnitude numbers

view details

Mike Stewart

commit sha b8b57e269c64f67bb4bbd1539da9c1d863077741

yaAGCb1: Updated change notes for executeOneInstruction

view details

Ronald Burkey

commit sha 62edbcc8c6021789df156749d71229308ba4313a

Merge pull request #1149 from virtualagc/yagcb1_fixes yaAGCb1: Fixed a few errors identified by SELF-CHECK

view details

Mike Stewart

commit sha f1b24fe79e7c40b04f21ab2600af17034b90acd8

yaAGC: Big refactor for improved scaler logic and cycle-accurate counter simulation.

view details

Mike Stewart

commit sha 3b0b9e4d07d51c80a6df1977b2ab3c8b3cd776a8

yaAGC: Added full simulation of the RHC counters

view details

Mike Stewart

commit sha 41b3c9eea0a6a99c00c1610fd5ad86462a04839f

yaAGC: Added simulation of the radar interface

view details

Mike Stewart

commit sha 56aa0350df5dad667e37a982cb927c6464151b0f

yaAGC: Added simulation of the GYROCMD output counter

view details

Mike Stewart

commit sha ed1f6db892992b4f2436302368819061d7c30af2

yaAGC: Added simulation of the five CDU drive counters

view details

Mike Stewart

commit sha 8a6705ba774918d6857d2f62769efcfe383c60b8

yaAGC: Added simulation of THRUST and EMSD counters

view details

Mike Stewart

commit sha d68dea3a351e9b4853a398fcc37ccc48c16e2a2b

yaAGC: Added simulation of the OUTLINK and ALTM output counters

view details

Mike Stewart

commit sha 25cbf6e399e6ac69a745d0677f5ade079a2b8984

yaAGC: Added a skeleton PulseOutput() function and changed output counters to use it

view details

Mike Stewart

commit sha 0307f3d0bda759ebbfc5bd165eac1fc4f8444018

yaAGC: Added a PulseInput(), which handles logic for incoming pulses to the AGC. PIPAs and uplink/crosslink are now fully simulated.

view details

Mike Stewart

commit sha 054ad6df1b48da18897164d84124e444ec1e2ea1

yaAGC: Integrated the LR and RR into the new PulseInput/PulseOutput interface

view details

push time in 12 days

Pull request review commentvirtualagc/virtualagc

Improved scaler logic and counter simulation for yaAGC

 SimulateDV(agc_t *State, uint16_t divisor)     uint16_t l = c(RegL);     int i; -    // Assume A contains the sign of the dividend-    dividend_sign = a & 0100000;+    // Assume A contains the sign of the dividend+    dividend_sign = a & 0100000;++    // Negate A if it was positive+    if (!dividend_sign)+      a = ~a;+    // If A is now -0, take the dividend sign from L+    if (a == 0177777)+      dividend_sign = l & 0100000;+    // Negate L if the dividend is negative.+    if (dividend_sign)+      l = ~l;++    // Add 40000 to L+    l = AddSP16(l, 040000);+    // If this did not cause positive overflow, add one to A+    if (ValueOverflowed(l) != AGC_P1)+      a = AddSP16(a, 1);+    // Initialize the remainder with the current value of A+    remainder = a;++    // Record the sign of the divisor, and then take its absolute value+    divisor_sign = divisor & 0100000;+    if (divisor_sign)+      divisor = ~divisor;+    // Initialize the quotient via a WYD on L (L's sign is placed in bits+    // 16 and 1, and L bits 14-1 are placed in bits 15-2).+    quotient_sign = l & 0100000;+    quotient = quotient_sign | ((l & 037777) << 1) | (quotient_sign >> 15);++    for (i = 0; i < 14; i++)+    {+        // Shift up the quotient+        quotient <<= 1;+        // Perform a WYD on the remainder+        remainder_sign = remainder & 0100000;+        remainder = remainder_sign | ((remainder & 037777) << 1);+        // The sign is only placed in bit 1 if the quotient's new bit 16 is 1+        if ((quotient & 0100000) == 0)+          remainder |= (remainder_sign >> 15);+        // Add the divisor to the remainder+        sum = AddSP16(remainder, divisor);+        if (sum & 0100000)+          {+            // If the resulting sum has its bit 16 set, OR a 1 onto the+            // quotient and take the sum as the new remainder+            quotient |= 1;+            remainder = sum;+          }+    }+    // Restore the proper quotient sign+    a = quotient_sign | (quotient & 077777);++    // The final value for A is negated if the dividend sign and the+    // divisor sign did not match+    c(RegA) = (dividend_sign != divisor_sign) ? ~a : a;+    // The final value for L is negated if the dividend was negative+    c(RegL) = (dividend_sign) ? remainder : ~remainder;+}++//-----------------------------------------------------------------------------+// These functions implement scaler timing logic. The scaler is a 33-stage+// binary counter whose outputs are used to time many things throughout the+// AGC. Each stage has four outputs -- the inverted and noninverted state for+// that stage (named, eg., FS09 and FS09/), and two timing pulses of the form+// FxxA and FxxB. Timing pulse FxxA is emitted when the stage transitions from+// a 1 to a 0, and timing pulse FxxB is emitted when the stage transitions+// from a 0 to a 1. The frequency of each stage can be calculated by the+// forumula (1.024 kHz)/(2^x), where x is the number of the stage.+//+// Our implementation of the scaler omits stages 1 and 2, since they are too+// fast and time things too finely detailed for an emulator to care about.+// We simply advance our scaler counter once at the beginning of every MCT,+// and if that causes stage 3 to increment, we generate all expected+// timing pulses.++// Timepulse F03B generates PIPA data strobes, causing all three to generate+// either a plus or a minus count request. This happens only when FS04 is+// set and FS05 isn't -- i.e, every fourth F03B.+static void+TimingSignalF03B(agc_t * State)+{+    if ((State->ScalerValue & (SCALER_FS05 | SCALER_FS04)) == SCALER_FS04)+      PulseOutput(State, OUTPUT_PIPA_DATA);+}++// Timepulse F04A clears the uplink-too-fast bit, which is set by each+// incoming uplink bit. If another uplink bit arrives before F04A occurs,+// the new bit will be dropped and the computer will be notified via+// channel 33 bit 11.+static void+TimingSignalF04A(agc_t * State)+{+    State->UplinkTooFast = 0;+}++// Timepulse F05A is far and away the busiest timing signal. It is used +// for some standby-powered circuitry that monitors voltage levels. We +// are not simulating power supply failures, and the input voltage must+// go well below its lower limit for the AGC power supply outputs to+// dip, so we only monitor the input voltage.+// +// It checks inputs for the three input traps (31A, 31B, and 32) and+// sets a bit for each if they are active. If F05B occurs before a+// triggered trap gets reset, a HANDRUPT will be generated.+//+// This timepulse also generates many output count requests: the BMAG/RHC+// and RNRAD input counters, and all output counters use this timepulse.+static int+TimingSignalF05A(agc_t * State)+{+    int CausedRestart = 0;+    int i = 0;+    int PulseType = 0;++    // First, perform standby-powered stuff. Has our input voltage+    // remained below the limit since F05B?+    if (State->InputVoltageLow)+    {+        // The input voltage is bad. If we're in standby, this generates+        // an input to the warning filter.+        if (State->Standby)+            State->GeneratedWarning = 1;++        if (!InhibitAlarms)+        {+            // If the alarm isn't disabled, the computer will be held in+            // restart (via signal STRT1) until the next F05A in which the+            // the voltage is back within limits. Trigger a GOJAM and set+            // the appropriate CH77 bit.+            State->RestartHold = 1;+            State->InputChannel[077] |= CH77_VOLTAGE_FAIL;+            CausedRestart = 1;+        }+    }+    else+    {+        // Voltage is good, so de-assert the STRT1 restart hold+        State->RestartHold = 0;+    }++    // That's it for standby-powered stuff, so leave if we're in standby+    if (State->Standby)+        return CausedRestart;++    // Set the PIPA pulse missing monitoring bits for each PIPA+    State->PipaMissX = 1;+    State->PipaMissY = 1;+    State->PipaMissZ = 1;++    // Check for any of the input traps to be triggered. If they are, and+    // the cause of the triggering doesn't go away before F05B, we'll+    // generate a HANDRUPT.+    if (State->Trap31A && ((State->InputChannel[031] & 000077) != 000077))+        State->Trap31APending = 1;++    if (State->Trap31B && ((State->InputChannel[031] & 007700) != 007700))+        State->Trap31BPending = 1;++    if (State->Trap32 && ((State->InputChannel[032] & 001777) != 001777))+        State->Trap32Pending = 1;++    // Check for RHC input pulses+    for (i = 0; i < 3; i++)+    {+        if (State->RHCCounts[i] > 0)+        {+            State->RHCCounts[i]--;+            if (State->InputChannel[013] & 0200)+                CounterRequest(State, COUNTER_RHCP + i, COUNTER_CELL_PLUS);+        }+        else if (State->RHCCounts[i] < 0)+        {+            State->RHCCounts[i]++;+            if (State->InputChannel[013] & 0200)+                CounterRequest(State, COUNTER_RHCP + i, COUNTER_CELL_MINUS);+        }+    }++    // Generate radar count requests if a valid radar is selected+    if (State->RadarSync)+    {+        if (State->InputChannel[013] & 04)+            PulseOutput(State, OUTPUT_LR_SYNC);+        else if ((State->InputChannel[013] & 03) != 0)+            PulseOutput(State, OUTPUT_RR_SYNC);+    }++    // Generate gyro drive pulses+    if (State->InputChannel[014] & 01000)+    {+        // At least one DINC is always generated regardless of the value+        // in the GYROCMD counter. The result of that DINC will determine+        // what happens next; if it generates a ZOUT, the drive active bit+        // and channel 14 bit 10 are cleared. Otherwise, the active bit is+        // set, which allows these F05A timing signals to generate drive+        // pulses to the gyros.+        CounterRequest(State, COUNTER_GYROCMD, COUNTER_CELL_PLUS);+        if (State->GyroDriveActive)+          PulseOutput(State, OUTPUT_GYROCMD_SET);+    }+    else+        State->GyroDriveActive = 0;++    // Generate CDU drive pulses if their respective channel 14 bits are+    // set. The output pulses themselves are generated during the DINC,+    // with a ZOUT resetting the channel 14 bit to disable the counter.+    if (State->InputChannel[014] & 040000)+      CounterRequest(State, COUNTER_CDUXCMD, COUNTER_CELL_PLUS);+    if (State->InputChannel[014] & 020000)+      CounterRequest(State, COUNTER_CDUYCMD, COUNTER_CELL_PLUS);+    if (State->InputChannel[014] & 010000)+      CounterRequest(State, COUNTER_CDUZCMD, COUNTER_CELL_PLUS);+    if (State->InputChannel[014] & 04000)+      CounterRequest(State, COUNTER_OPTYCMD, COUNTER_CELL_PLUS);+    if (State->InputChannel[014] & 02000)+      CounterRequest(State, COUNTER_OPTXCMD, COUNTER_CELL_PLUS);++    // THRUST and EMSD operate identically, with THRUST being enabled by+    // channel 14 bit 4, and EMSD being enabled by bit 5. For these,+    // F05A is responsible for both generating DINC requests *and*+    // sending the resulting output pulses. A POUT or a MOUT on the+    // first DINC will set a bit that allows plus or minus pulses,+    // respectively, on subsequent F05As. These bits are never cleared+    // until the CH14 enable bits are cleared, so if the value in the+    // counter changes sign for some reason, both plus and minus output+    // pulses will be generated until the counter is disabled.+    if (State->InputChannel[014] & 010)+    {+        if (State->ThrustPlusActive)+          PulseOutput(State, OUTPUT_THRUST_PLUS);+        if (State->ThrustMinusActive)+          PulseOutput(State, OUTPUT_THRUST_MINUS);++        CounterRequest(State, COUNTER_THRUST, COUNTER_CELL_PLUS);+    }++    if (State->InputChannel[014] & 020)+    {+        if (State->EMSPlusActive)+          PulseOutput(State, OUTPUT_EMSD_PLUS);+        if (State->EMSMinusActive)+          PulseOutput(State, OUTPUT_EMSD_MINUS);++        CounterRequest(State, COUNTER_EMSD, COUNTER_CELL_PLUS);+    }++    // OUTLINK and ALTM are also almost identical. OUTLINK is enabled+    // by channel 14 bit 1. After this bit is set to 1, nothing happens+    // until the following GTSET, which sets up the output circuitry.+    // The first F05A after this GTSET, a "1" output pulse is generated+    // as a sync marker. This F05A will also generate a SHINC request,+    // as will every subsequent F05A until the outlink counter is+    // disabled by another GTSET. +    //+    // The first F05A of an outlink will also clear the enable flip-flop,+    // channel 14 bit 1. However, this bit will still read as 1 to+    // software, because for reading its state is ORed together with+    // the "outlink active" flip-flop.+    //+    // ALTM behaves almost identically. It is enabled by channel 14 bit+    // 3. It can target one of two pairs of output pins; altitude if+    // channel 14 bit 2 is 0, and altitude rate if it is 1. This+    // selection is "checked" with every output pulse, so misbehaving+    // software can change which interface is being addressed in the+    // middle of an output cycle.+    if (State->OutlinkActive)+    {+        if (State->OutlinkStarting)+        {+            State->OutlinkStarting = 0;+            PulseOutput(State, OUTPUT_OUTLINK_ONE);+            State->InputChannel[014] &= ~01;+        }+        else+          CounterRequest(State, COUNTER_OUTLINK, COUNTER_CELL_ZERO);+    }++    if (State->AltActive)+    {+        if (State->AltStarting)+        {+            State->AltStarting = 0;+            State->InputChannel[014] &= ~04;+            if (State->InputChannel[014] & 02)+              PulseOutput(State, OUTPUT_ALTRATE_ONE);+            else+              PulseOutput(State, OUTPUT_ALT_ONE);+        }+        else+          CounterRequest(State, COUNTER_ALTM, COUNTER_CELL_ZERO);+    }++    return CausedRestart;+}++// Timepulse F05B checks to see if any voltage sources are out of limits,+// and if they are, notes it down. If the problem hasn't been resolved+// by F05A, we'll generate an alarm. It also generates HANDRUPTs if any+// of the input traps are enabled and triggered.+// Timing pulses GTSET, GTRST, and GTONE are potentially generated,+// depending on the state of scaler stages 6-9. These pulses are used+// by the radar, outlink, and altimeter interfaces.+static void+TimingSignalF05B(agc_t * State)+{+    unsigned GtsetType;+    // If the input voltage is below the voltage fail circuit threshold,+    // set a bit for F05A to check.+    if (State->InputVoltagemV < VFAIL_THRESHOLD)+        State->InputVoltageLow = 1;++    if (State->Standby)+        return;++    // Set the PIPA fail bit if any expected PIPA pulses were not received+    if (State->PipaMissX || State->PipaMissY || State->PipaMissZ)+      State->InputChannel[033] &= ~010000;++    // If any of the input traps are pending, generate a HANDRUPT and+    // disable the tripped trap.+    if (State->Trap31APending)+    {+        State->Trap31A = 0;+        State->Trap31APending = 0;+        State->InterruptRequests[RUPT_HANDRUPT] = 1;+    }++    if (State->Trap31BPending)+    {+        State->Trap31B = 0;+        State->Trap31BPending = 0;+        State->InterruptRequests[RUPT_HANDRUPT] = 1;+    }++    if (State->Trap32Pending)+    {+        State->Trap32 = 0;+        State->Trap32Pending = 0;+        State->InterruptRequests[RUPT_HANDRUPT] = 1;+    }++    // Handled GTSET, GTRST, and GTON-driven logic+    GtsetType = State->ScalerValue & SCALER_GTSET;+    if (GtsetType == SCALER_GTSET)+    {+        // If the radar gate counter has reached 9, begin generating sync+        // pulses and getting count requests back.+        if (State->RadarGateCounter == 9)+          State->RadarSync = 1;++        // Outlink and tape meter outputs function identically; GTSET will+        // begin an outgoing pulse sequence if there is not one already+        // active, otherwise it will end the ongoing one and clear the+        // channel enable bit.+        if (State->OutlinkActive)+        {+            State->InputChannel[014] &= ~01;+            State->OutlinkActive = 0;+        }+        else if (State->InputChannel[014] & 01)+        {+            State->OutlinkActive = 1;+            State->OutlinkStarting = 1;+        }++        if (State->AltActive)+        {+            State->InputChannel[014] &= ~04;+            State->AltActive = 0;+        }+        else if (State->InputChannel[014] & 04)+        {+            State->AltActive = 1;+            State->AltStarting = 1;+        }+    }+    else if (GtsetType == SCALER_GTRST)+    {+        // If a radar sync was active, stop it, generate a RADARUPT, and+        // reset all of the related state information+        if (State->RadarSync)+        {+            State->InterruptRequests[RUPT_RADARUPT] = 1;+            State->InputChannel[013] &= ~010;

This state update needs to propagate to all connected clients / peripheral simulations (via ChannelOutput wrapped by CpuWriteIO).

            CpuWriteIO(State, 013, ReadIO(State, 013) & ~010);
thewonderidiot

comment created time in 12 days

PullRequestReviewEvent

startedDatabaseCleaner/database_cleaner

started time in 13 days

startedtroessner/reek

started time in 15 days

startedstitchfix/stitches

started time in 15 days

startedaappleby/MetroBoy

started time in 19 days

startedMikhailGolubtsov/git-mv-changes

started time in 23 days

startedjashandeep-sohi/webcam-filters

started time in 25 days

push eventmichaelfranzl/docx_converter

Abhilash Reddy

commit sha e9323e085e799d162b519435f1835e9588341fb8

Typo fix for gem install (#6) * Update README.md * Update README.md

view details

push time in a month

PullRequestReviewEvent