OK, Good start. First I think this will have to be your main and grabbing input will have to be your interrupt. I say this because even if you used pure ASM to get in the ISR, it will take at least 8 ASM instructions for the context save and restore. This leaves you almost no room to do anything. On the other hand, if the signalk generation is the main, with an interrupt call for the keypress, maybe it will be ok. you will get a glitch or 2, but only when you change freq.

No, lets see how to speed this up a bit.
First remove the else statements. you are not using them so you can get rid of them. I don't think this will speed it up, but lets see.

After you try that, change the counters to count down instead of up. Checking if freq = 0 should be much faster then if freq >= something. The reason for this is in the compiled code, it should compile to be something like this:
Code:
DECF freq    'decrenment freq
BTFSS freq  'test if freq is zero, if not skip the next step
JMP notzero
MOVLW 5
MOVF freq
notzero:
reutrn
In order to test for equal or greater then any number other then zero, first the number must be subtracted from the counter, then status.zero must be tested. If not zero, then borrow or carry must be tested and the program will branch accordingly. Does this make sense?

After you try these 2 things, report back with the results. There is at least 1 more thing we can do, but I want you to try each thing 1 at a time and understand why it worked or didn't work.