Ideas:

(Note my 16F877 datasheet is not recent)

Port B has interrupt on change feature, page 132 of 218. I would use that port to check for transitions.

The 16F877 has 3 timers, I would use one for low-high transitions and another for high-low.

When port B senses a change, check if going high or low and start the appropriate timer.

At next port B change, check which transition it is, then check if you started that timer, and if yes then check the time elapsed on the timer.

If at the desired frequency, stop timer and trigger whatever event you want, or restart timer again. This way you can check going high and low transitions at the same time. You can check if within a range of desired frequency also, possibly a 5% tolerance - depends on your needs. You can also use a counter to check how many pulses was detected at that frequency (stability test - reset if less than X transistions).

It may be a simplified approach, but it may be all you need for your application. You can use DT INTERRUPTS to control the timers (it can control a LOT of things), it makes things so much easier than trying to figure what registers to set in the datasheet.

About DT interrupts, make sure you use the version for 16F PICs from DT's site (it's all labelled properly).

If the maximum oscillator speed of 20 MHz of the 16F877 is not enough, consider an 18F. I used the 16F628 and 16F877 when I first started, now I use the 18F24K22 series, they can run at 64 MHz on internal oscillator.

One last note, don't try to do everything at once. Start with one part of your logic, and build on it as you prove it works. Test each new section as you add them. Personally, I test them individually in small programs, then incorporate them in the main program as they are tested OK.

Good luck!

Robert