Porting bit operations from Python to C#

84 views Asked by At

I am working on a C# port of the Adafruit_CircuitPython_RFM69 Python library which is an SPI radio module library that I'm using with a Raspberry Pi.

I have most of the python properties ported over and tested/working successfully, except for being able to get/set the frequency_mhz & frequency_deviation Python properties.

I'm unable to receive any radio packets with my C# port, but the Python version works flawlessly, and I suspect the two properties in question is the reason why.

Frequency:

// works? - not perfectly accurate
rfm.Frequency = 433;
Console.WriteLine("Frequency: {0}", rfm.Frequency); // after setting 'rfm.Frequency = 433' the get method reports '432'

private int GetFrequency()
{
    // FRF register is computed from the frequency following the datasheet.
    // See section 6.2 and FRF register description.
    // Read bytes of FRF register and assemble into a 24-bit unsigned value.
    byte msb = ReadByte(_REG_FRF_MSB);
    byte mid = ReadByte(_REG_FRF_MID);
    byte lsb = ReadByte(_REG_FRF_LSB);
    int frf = ((msb << 16) | (mid << 8) | lsb) & 0xFFFFFF;
    int frequency = (frf * _FSTEP) / 1000000;
    return frequency;
}

private void SetFrequency(int freq)
{
    if (freq < 290 || freq > 1020)
        throw new ArgumentOutOfRangeException(nameof(freq), freq, "frequency must be between range(290, 1020)");

    // Calculate FRF register 24-bit value using section 6.2 of the datasheet.
    int frf = ((freq * 1000000) / _FSTEP) & 0xFFFFFF;

    // Extract byte values and update registers.
    byte msb = (byte)(frf >> 16);
    byte mid = (byte)((frf >> 8) & 0xFF);
    byte lsb = (byte)(frf & 0xFF);

    WriteByte(_REG_FRF_MSB, msb);
    WriteByte(_REG_FRF_MID, mid);
    WriteByte(_REG_FRF_LSB, lsb);
}

FrequencyDeviation:

// works? - not perfectly accurate
rfm.FrequencyDeviation = 250000;
Console.WriteLine("FrequencyDeviation: {0}", rfm.FrequencyDeviation); // after setting 'rfm.FrequencyDeviation = 250000' the get method reports '249978'

private int GetFrequencyDeviation()
{
    byte msb = ReadByte(_REG_FDEV_MSB);
    byte lsb = ReadByte(_REG_FDEV_LSB);
    return _FSTEP * ((msb << 8) | lsb);
}

private void SetFrequencyDeviation(int value)
{
    if (value < 0 || value > _FSTEP * 16383) // fdev is a 14-bit unsigned value
        throw new ArgumentOutOfRangeException(nameof(value), value, $"frequency deviation must be between range(0, {_FSTEP * 16383})");

    // Round up to the next closest integer value with addition of 0.5.

    int fdev = (int)((value / _FSTEP) + 0.5) & 0x3FFF;
    WriteByte(_REG_FDEV_MSB, (byte)(fdev >> 8));
    WriteByte(_REG_FDEV_LSB, (byte)(fdev & 0xFF));
}

Any help/pointers is greatly appreciated, thanks in advance!

I did some testing for getting/setting the two properties in Python and they both return the exact values that were set, I tried many different casts and rounding methods in my C# port to no avail.

I'm expecting to get the same input/output as Python, and I'm unsure why I'm not.

I can't figure out why I can't do the exact same bit operations in C# that are done in the Adafruit Python code. I know it must have something to do with the C# type differences but I'm unsure how to combine/cast the Python types to C# properly.

Here is the full C# code

Here is the RFM69 datasheet just in case.

0

There are 0 answers