When to use a discrete callback in DifferentialEquations.jl

I have a fairly large model I am trying to solve (~100 differential equations). There is a particular parameter that changes every 28 days. Right now, I switch this parameter using a callback function

function model!(du, u, params, t) 
   a bunch of equations involving params.r 
end

condition(u,t,integrator) = round(t, digits=3) ∈ collect(28:28:800) 
function dose!(integrator)     
   integrator.p.r = 1 - integrator.p.r
end
cb = DiscreteCallback(condition, dose!, save_positions=(false,false))

function run_model() 
    prob = ODEProblem(model!, u0, tspan, params
    sol = solve(prob, callback = cb)
end 

So you see, every 28 time steps, I basically switch the r parameter that cycles through 0 and 1. My question is, is it cheaper and better to do this in the model! function directly and get rid of callbacks? Can I have something like

function model!(du, u, params, t) 
   if t satisfies condition 
       params.r = 1 - params.r 
   end 
   a bunch of equations involving params.r 
end

From preliminary testing this seems to work, but I am not sure what the correct, more efficient way of doing it is.

As you have it written, if your timesteps are small enough (~1e-4 s), you could unintentionally dose multiple times depending on the precision specified in round(t, digits=3). Are you using a fixed time step of one day? Seems like you may want a PresetTimeCallback.

That decrementing in the function f is not safe because time isn’t monotonic in an adaptive ODE solver. You might decrement at a given time point twice.