Softata: Open AI and Enums with Blockly & Swagger Part 3
The previous two posts discussed Blockly and Swagger Controller methods that take enum types as a parameters. With Blockly, each enum type so used, manifests as a block with a dropdown list of the enum literals. How can that be used for a controller parameter where the enum literals depend upon another parameter to the block. In particular, for the Display.Misc() method where each display type has a different enum list of miscellaneous options.
Context |
---|
With the Blockly blocks generated from the controller SoftataGPIOADController, you enter the values, such as a pin number and the code needs to validate them. An additional controller GroveGroveController has been added that mirrors the SoftataGPIOADController functionality. enums are used as parameters for GroveGroveController rather than numeric values. An object block is generated for each enum type used as a controller parameter. This makes things simpler because parameters are selectable and valid as you can only select literals in an enum list. |
enums and Display Misc Commands
Displays have a Misc() command that are a gateway to miscellaneous commands that are specific to each display type.
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._
Display Commands:
public enum GroveDisplayCmds{getpins=0, getMiscCmds=1, setupDefault=2, setup=3, clear=4,backlight=5,setCursor=6, writestrngCMD=7,cursor_writestringCMD=8,homeCMD=9, misc=10,dispose=11, getDisplays=255 }
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 the 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 displays 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.
Topic | Subtopic | |
This Category Links | ||
Category: | Softata Index: | Softata |
Next: > | Softata | Blockly Session |
< Prev: | Softata | Open AI and Enums with Blockly & Swagger Part 2 |