I did this a few years ago for a bespoke system I designed and built. You can see the system I designed actually moving the laser head in this video (unfortunately Vimeo requires a login).
I did it with a lookup table (a C static array generated by a python script). If you want smooth motion, you want constant acceleration, so that there is a small, constant force on the load, according to F=ma. You can then accelerate to whatever final velocity you define.
If you have an integer that defines the time until the next pulse, your static array of constants which gives your initial step (which will be longest), thereafter each step is a little shorter. Make the table large enough so that you can get to your target velocity.
Of course, if you only need a small distance you don't have to use all the steps. In my system, because there was always a fixed target position, a "recipe" is calculated before starting the move, which defines how many steps of the ramp must be used used, and for how many steps the head must remain at maximum velocity, to get to that target.
In real time, each time a pulse is emitted, the next value in the lookup table defines when the next pulse will happen.
It's a few years ago, and I don't remember the equation to generate the steps. I need to look up the source code, I will do so in a few days and post it here. For my purpose (moving a laser head around an XY table) it worked very well.
The maths to get the profile was derived from this link. However I didn't want or need to generate the profile in real time.