Search code examples
c#uwpraspberry-piwindows-10-iot-core

HT16K33-based fourteen-segment control does not always show the correct characters for given bitmask on Windows 10 IoT Core


I want to show a character on a fourteen segment control display (4 side by side) on my Pimoroni RainbowHAT for my Raspberry running Microsoft Windows 10 IoT Core.

For some messages like "HELL" (from "Hello) does my source work as expected but for others like "DEMO" it shows garbage. This is weird for me, because both messages include the letter "E". But it does only work once.

My last idea is, that bitmask[1] & 0xFF; is not the same as bit-shifting (bitmask[0] >> 8) && 0xFF if we would asume a not split up bitmask.

Example messages (Input -> Shown on display)

  • "HELL" -> HELL
  • "DEMO" -> " ," (3 spaces, comma)

Source example (Full source: GitHub)

Segment buffer that will be written to the device:

private readonly byte[] segmentBuffer = Enumerable.Repeat(Convert.ToByte(0b00000000), BUFFER_SIZE).ToArray();

Bitmask for letter D:

private static readonly Dictionary<char, byte[]> BITMASK_DICTIONARY = new Dictionary<char, byte[]>{   
    { 'D',  new byte[]{0b00010010, 0b00001111},
      .... 
    }
};

Getting bitmask for char:

private byte[] ConvertCharToBitmask(char character)
{
    // Check if char is available.
    if(BITMASK_DICTIONARY.Keys.Contains(character))
    {
        return BITMASK_DICTIONARY[character];
    }

    // If not, return default (spaces).
    ...
}

Writing changes to the device (message = "DEMO"):

for (int i = 0; i < message.Length; i++)
{
    var bitmask = ConvertCharToBitmask(message[i]);
    segmentBuffer[i * 2] = Convert.ToByte(bitmask[0] & 0xFF);
    segmentBuffer[i * 2 + 1] = Convert.ToByte(bitmask[1] & 0xFF);
}

// Write buffer to device.
ht16k33.Write(segmentBuffer);

Links


Solution

  • From the code in your post, it seems incorrect for setting the segmentBuffer. Please try with following code.

            for (int i = 0; i < message.Length; i++)
            {
                var bitmask = ConvertCharToBitmask(message[i]);
                Logger.Log(this, $"Writing char: '{message[i]}' at index: {i}.");
                segmentBuffer[i * 2] = Convert.ToByte(bitmask[1] & 0xFF);
                segmentBuffer[i * 2 + 1] = Convert.ToByte(bitmask[0] & 0xFF);
            }
    

    You transferred 'D': 0b0001001000001111 to { 'D', new byte[]{0b00010010, 0b00001111}, according with the code in python, segmentBuffer[i * 2] should be the lower position byte, whereas segmentBuffer[i * 2 + 1] should be higher.

    I don't have a device to test this issue. If it does not work, please feel free let me know.

    Update:

    The following code seems more match with the code in python.

        private static readonly Dictionary<char, int> BITMASK_DICTIONARY = new Dictionary<char, int>
        {
            { ' ',  0b0000000000000000  },
            { 'D',  0b0001001000001111  },
        };
    
        private int ConvertCharToBitmask(char character)
        {
            // Check if char is available.
            if (BITMASK_DICTIONARY.Keys.Contains(character))
            {
                return BITMASK_DICTIONARY[character];
            }
    
            // If not, return default.
            return GetDefaultCharBitmask();
        }
    
        private int GetDefaultCharBitmask()
        {
            return BITMASK_DICTIONARY[DEFAULT_BITMASK_CHAR];
        }
    
    
        public void Show(string message)
        {
            // Ensure message has valid length.
            if(message.Length > NUMBER_OF_SEGMENTS)
            {
                throw new OperationCanceledException($"Maximum message length is {NUMBER_OF_SEGMENTS} characters.");
            }
    
            // Update buffer
            Logger.Log(this, $"Show for {message}");
            for (int i = 0; i < message.Length; i++)
            {
                var bitmask = ConvertCharToBitmask(message[i]);
                Logger.Log(this, $"Writing char: '{message[i]}' at index: {i}.");
                segmentBuffer[i * 2] = Convert.ToByte(bitmask & 0xFF);
                segmentBuffer[i * 2 + 1] = Convert.ToByte(bitmask >> 8 & 0xFF);
            }
    
            // Write buffer to device.
            ht16k33.Write(segmentBuffer);
        }