The previous post discussed Blockly and Swagger Controller Setup methods that take an Device Type enum as a parameter. It manifests as a dropdown list of the device enum literals. How can that be applied for any Controller Method that can use other enum types as parameters, manifesting as dropdown lists in Blockly Blocks and Swagger Methods? Also covered is where each display type has a specific list, as an enum type, of the misc commands. But the Display.Misc block is general purpose (not to specific to the display type) and so what is needed is a single enum list of all Display.misc display Misc enums.

In what follows, this might all seem like a bit of hotchpotch but it does work!

Context

Misc: Miscellaneous commands for a specific display.

Most of the Blockly Display blocks are generic to all displays. That is,there is a defined set of commands that all Softata displays will implement. Where not relevant for a specific display the method is a dummy method, just returning as true without any actions. All displays implement the misc command but that is gateway to commands specific for each display type.

Other enum types as Blockly parameters

This approach can also be used where the Controller parameter can be constrained an enum list.

  • enum analoginputs: byte {A0, A1, A2}
  • enum serial: byte {com1, com2} These then could be selectable in relevant blocks.

Set GPIO Digital Pin Mode

   public enum GroveGPIOPins { p16,p18,p20, p17,p19,p21}
   public enum DigitalPinMode { Input , Output }

These enum create the GroveGPIOPins and DigitalPinMode blocks in the Objects that can be used with the block created by this Controller method:

    [Route("SetDigitalPinModeGrove")]
    [HttpPost]
    public IActionResult SetDigitalPinModeGrove(GroveGPIOPins pin, DigitalPinMode mode)
    {
        byte pinn = 0;
        // No validation required
        switch(pin)
        {
            case GroveGPIOPins.p16: pinn = 16; break;
            case GroveGPIOPins.p18: pinn = 18; break;
            case GroveGPIOPins.p20: pinn = 20; break;
            case GroveGPIOPins.p17: pinn = 17; break;
            case GroveGPIOPins.p19: pinn = 19; break;
            case GroveGPIOPins.p21: pinn = 21; break;
        }
        SoftataLib.Digital.SetPinMode((byte)pinn, (PinMode)mode);
        return Ok($"Pin:{pin} Mode:{(PinMode)mode}");
    }

And so you get a dropdown list of valid GPIO pins for the Grove Pico shield and the two options for pin mode (Input or Output).

A major task was though for the Display.Misc commands. Each display type has a specific set of misc commands. But it is desirable just to have one Display.misc block taking the instance index and an enum of misc commands. The original Display.Misc block takes a byte parameter that is interpreted on the Arduino device in the context of the display type. Each display type has an enum list of misc commands. For example for the Bargraph and LCD1602:

public enum BARGRAPHMiscCmds: byte { flow, flow2, setLed, clrLed, toggleLed, setLevel, exercise, BARGRAPHMiscCmds_MAX }
public enum LCD1602MiscCmds : byte {home, autoscroll, noautoscroll, blink, noblink, LCD1602MiscCmds_MAX }

Note that there is overlap with the ordinals. flow and home both have the same ordinal zero. flow2 and autoscroll both have the ordinal of 1. Interpretation is within the code for each display type on the Arduino device. Note also that each list has _MAX enum value as the last one in th e list.

The solution was to create a “mega” enum list of all display misc enums and then make each specific display type enum list a subset of that. This was suggested here on StackOverflow, the first answer. This is implemented. See The “Mega” enum at the bottom of this post.

Thus each subset of enums has a different range of ordinals. To get back the original ordinal for each item in the, now subset, you subtract the first “sub”list item from its mega list ordinal. Doing this formally:

public static class DisplayMiscEnumFirstCmd
{
    public static AllDisplayMiscCommands LCD1602MiscCmds = AllDisplayMiscCommands.home;
    public static AllDisplayMiscCommands NEOPIXELMiscCmds = AllDisplayMiscCommands.setpixelcolor;
    public static AllDisplayMiscCommands OLEDMiscCmds = AllDisplayMiscCommands.drawCircle;
    public static AllDisplayMiscCommands BARGRAPHMiscCmds = AllDisplayMiscCommands.flow;
}

Then …

public static bool MiscCmd(byte linkedListNo, DisplayDevice displayType, AllDisplayMiscCommands cmd, byte[]? _data = null)
{
    byte command = 0;
    AllDisplayMiscCommands start = 0;
    AllDisplayMiscCommands max = 0;
    switch (displayType)
    {
        case DisplayDevice.BARGRAPH:
            start = DisplayMiscEnumFirstCmd.BARGRAPHMiscCmds;
            max = AllDisplayMiscCommands.BARGRAPHMiscCmds_MAX;
            break;
        ... etc
    }
    // Validation
    if ((cmd >= start) && (cmd < max))
    {
        command = cmd - start;
    }
    else
        return false;
    
    ...
    ...

command is then what is forwarded to the Arduino service.

Note though that there is now an extra parameter DisplayDevice displayType in th block. This is so that the switch statement can subtract the correct initial enum value for the display type. This is actually locked in when the display is setup but is not recorded in SoftataLib. A query could be make to the Arduino Softata service (not implemented). But it was decided that it is simpler just to require that extra parameter.

So the Blockly code now is

Also, another parameter is required for several of the commands. For example, the set,clr,toggle Bargrpah commands require a LED segment 1 … 10. (2Do)


The “Mega” enum

This gives each Misc command across all dispaly a unique ordinal.

    public enum AllDisplayMiscCommands : byte 
    {
    /* LCD1602MiscCmds */
        home, autoscroll, noautoscroll, blink, noblink,/* Add Here, */ LCD1602MiscCmds_MAX,
    /* NEOPIXELMiscCmds */
        setpixelcolor, setpixelcolorAll, setpixelcolorOdds, setpixelcolorEvens, setBrightness, /* Add Here, */NEOPIXELMiscCmds_MAX ,
    /* OLEDMiscCmds */
        drawCircle, drawFrame, /* Add Here, */ OLEDMiscCmds_MAX ,
    /*BARGRAPHMiscCmds */
        flow, flow2, setLed, clrLed, toggleLed, setLevel, exercise, /* Add Here, */ BARGRAPHMiscCmds_MAX 
    }

    enum LCD1602MiscCmds : byte { home = AllDisplayMiscCommands.home, autoscroll = AllDisplayMiscCommands.autoscroll, noautoscroll = AllDisplayMiscCommands.noautoscroll, blink = AllDisplayMiscCommands.blink, noblink = AllDisplayMiscCommands.noblink,/* Add Here, */ LCD1602MiscCmds_MAX = AllDisplayMiscCommands.LCD1602MiscCmds_MAX }
    enum NEOPIXELMiscCmds : byte { setpixelcolor = AllDisplayMiscCommands.setpixelcolor, setpixelcolorAll  = AllDisplayMiscCommands.setpixelcolorAll, setpixelcolorOdds  = AllDisplayMiscCommands.setpixelcolorOdds, setpixelcolorEvens = AllDisplayMiscCommands.setpixelcolorEvens, setBrightness = AllDisplayMiscCommands.setBrightness, /* Add Here, */ NEOPIXELMiscCmds_MAX = AllDisplayMiscCommands.NEOPIXELMiscCmds_MAX }
    public enum OLEDMiscCmds : byte { drawCircle = AllDisplayMiscCommands.drawCircle, drawFrame = AllDisplayMiscCommands.drawFrame, /* Add Here, */ OLEDMiscCmds_MAX = AllDisplayMiscCommands.OLEDMiscCmds_MAX }
    public enum BARGRAPHMiscCmds: byte { flow = AllDisplayMiscCommands.flow, flow2 = AllDisplayMiscCommands.flow2, setLed = AllDisplayMiscCommands.setLed, clrLed = AllDisplayMiscCommands.clrLed, toggleLed = AllDisplayMiscCommands.toggleLed, setLevel = AllDisplayMiscCommands.setLevel, exercise = AllDisplayMiscCommands.exercise, /* Add Here, */ BARGRAPHMiscCmds_MAX = AllDisplayMiscCommands.BARGRAPHMiscCmds_MAX }

Note the use of the _MAX ordinal for each display type. These, whilst not actual misc commands, indicate the upper limit for each display type. In the dropdown list, the enum literals for a display type are immediately above that display’s max literal.

The down arrow is click in the AllDisplayMiscCommands revealing all of the Misc commands. Scrolling down, the Bargraph.Misc commands are between OLEDMiscCmds_MAX down to the BARGRAPHMiscCmds_MAX. That way, the Maxs bracket a display type’s Misc commands.



 TopicSubtopic
   
 This Category Links 
Category:Softata Index:Softata
<  Prev:   Softata