Alternatives to LTSpice that are more digitally oriented?
I found what I wanted after reading documentation for the xspice module available in ngspice. It allows me to write models for my digital components in C and then simulate peripheral discrete components using existing spice models for transistors, resistors etc. I'm still experimenting with this feature but so far it has been very promising because I can model any firmware based digital controller in between inputs and outputs of a digital component defined in the schematic.

Here is a small throwaway example of a custom pwm component:


I then export this as a spice netlist from kicad:

* Sheet Name: /
A1  Net-_A1-Pad1_ GND Net-_A1-Pad3_ Net-_A1-Pad4_ MKPWM01
V1  Net-_A1-Pad1_ GND 3.3v
R3  OUT GND 50k
R2  Net-_A1-Pad3_ GND 10k
R1  Net-_A1-Pad1_ Net-_A1-Pad3_ 10k
C1  OUT GND 10n
R4  OUT Net-_A1-Pad4_ 50k

.end


Then I add a little wrapper script where I add ngspice commands for my circuit:

.model mkpwm01 mkpwm01 (freq = 100)

.include "spice_test.cir"

.control
tran 1ms 100ms
plot v(OUT)
.endc

.end


And finally I add code model for mkpwm component under src/xspice/icm and then compile ngspice:

void cm_d_mkpwm01(ARGS) {               
    if (ANALYSIS == DC || ANALYSIS == TRANSIENT) {
        double out = sin(TIME * PARAM(freq) * 2.f * M_PI);

        if(out &gt; 0) out = INPUT(vcc);   
        else out = INPUT(gnd);          

        OUTPUT(out) = out;              
    }   
}       


And the model definition (.ifs) file:

NAME_TABLE:

Spice_Model_Name:      mkpwm01          
C_Function_Name:       cm_d_mkpwm01     
Description:           "pwm generator"  


PORT_TABLE:

Port_Name:           vcc                gnd             in                 out
Description:         "vcc"              "gnd"           "input"            "output"
Direction:           in                 in              in                 out
Default_Type:        v                  v               v                  v
Allowed_Types:       [v]                [v]             [v]                [v]
Vector:              no                 no              no                 no
Vector_Bounds:       -                  -               -                  -
Null_Allowed:        no                 no              no                 no


PARAMETER_TABLE:

Parameter_Name:     freq                
Description:        "frequency"         
Data_Type:          real
Default_Value:      1                   
Limits:             [1e-12 -]           
Vector:              no                 
Vector_Bounds:       -                  
Null_Allowed:       yes           


Then finally running the wrapper script produces the result:



Very happy so far. Now time to simulate a more complex circuit :-)

Note: I originally added the xspice component as a digital component but that did not work because I got error "node can not be both digital and analog" so I had to change the pins to be analog (type v). The ngspice manual explains different pin types. Also the duty cycle input is not really implemented in the code.. Anyway, I still probably have a lot to learn how xspice api works but so far I think I found exactly what I need and hopefully this helps someone to start using ngspice for customized circuit simulation.