I'm writing a simple application in Python that sends and receives data over binary PSK using audio signal. I used cos() for 0 and -cos for 1. On the receiver side I figured I can demodulate by multiplying the signal by 2*cos so this will essentially shift the signal below and above x axis for corresponding bits. It works great. Now, I'm thinking about using low pass filter or maybe averaging the data in the time frames to get the output "square wave"? What would be the best/most efficient approach here? I'm might be a pro software engineer but tinkering with this as a hobbyist, thus probably very basic question :)
An "integrate and dump" filter is a common approach for this application, which is essentially an averaging filter averaged optimally over your symbol period. To implement this, you simply reset your accumulator at the symbol boundaries, accumulate your output over the symbol period and then "dump" your result by taking the accumulated output as the result before resetting it again. For a rectangular pulse shape BPSK in the presence of additive white Guassian noise, this is the optimum matched filter. (However in most wireless applications, the BPSK signal would not have a rectangular pulse but be pulse shaped such as with root-raise cosine pulse shaping in the transmitter, and we would then weight the received samples with another root-raised cosine impulse response in the integration for optimum matched filtering).
Note, unless you have a shared clock between your transmitter and receiver, you will likely also need to implement some form of carrier recovery to track clock variations between your transmitter and receiver (otherwise once you drift 90 degrees, your cosine will be a sine and you will get no output in that condition!). And as described above, you will need some form of timing recovery to establish when your start of the symbols are referenced to your signal as received.
I have detailed these in the following posts: