# SFBReactor Class Reference

The SFBReactor manages the SFB reflex triggering system: It determines how an SFB will react to any given packet type. More...

`#include <SFBReactor.h>`

Collaboration diagram for SFBReactor:

[legend]

## Public Types
enum | { TRIGGER_IF_BROKEN = 0x01, TRIGGER_EMPTY = 0x02, TRIGGER_SUPPRESSED = 0x04, TRIGGER_RESERVED3 = 0x08, TRIGGER_RESERVED4 = 0x10, TRIGGER_RESERVED5 = 0x20, TRIGGER_RESERVED6 = 0x40, TRIGGER_RESERVED7 = 0x80, TRIGGER_FIRST_PARTITION = 0x100, TRIGGER_NORTH = TRIGGER_FIRST_PARTITION<<NORTH, TRIGGER_SOUTH = TRIGGER_FIRST_PARTITION<<SOUTH, TRIGGER_EAST = TRIGGER_FIRST_PARTITION<<EAST, TRIGGER_WEST = TRIGGER_FIRST_PARTITION<<WEST, TRIGGER_SPINE = TRIGGER_FIRST_PARTITION<<SPINE, TRIGGER_MEMORY = TRIGGER_FIRST_PARTITION<<WMEM, TRIGGER_BRAIN = TRIGGER_FIRST_PARTITION<<BRAIN, TRIGGER_ALL_PARTITIONS }
## Public Member Functions
void | reset ()
int | faceToFlag (const u32 face)
u8 | reflexes (const PacketHandler *table, int length)
| Make an array of PacketHandler's available for use as reflex handlers.
void | reflex (const char type, PacketHandler pfunc, int partitions=TRIGGER_SPINE, bool ifBroken=false)
| Create a reflex association between a particular character type, and a particular PacketHandler function pfunc.
void | reflexReflex (const char type, PacketHandler pfunc, int partitions=TRIGGER_SPINE, bool ifBroken=false)
void | implReflex (const char type, PacketHandler pfunc, int partitions=TRIGGER_SPINE, bool ifBroken=false)
bool | reflexExists (const char type, int partitions=TRIGGER_ALL_PARTITIONS)
void | suppress (const char type, int partitions)
void | allow (const char type, int partitions)
void | otherwise (PacketHandler pfunc, int partitions=TRIGGER_BRAIN, bool allowBroken=false)
| Add a 'catch-all' handler.
void | empty (PacketHandler pfunc, int partitions=TRIGGER_SPINE, bool allowBroken=false)
void | triggerUp ()
bool | inHandler ()
| Are we currently executing inside a packet handler function?
u8 | source ()
u8 | getFlags (const char type)
void | trigger (u8 *packet, u8 face)
| Attempt to trigger reflexes on packet, as though it had arrived on face.
bool | canTrigger ()
| Check if it is possible to trigger reflexes on a packet at this time.
## Friends
void | reflex (const char type, PacketHandler ph, int flags)
| Equivalent to Body.reflex(type,ph,flags).

## Detailed Description

The SFBReactor manages the SFB reflex triggering system: It determines how an SFB will react to any given packet type.

## Member Enumeration Documentation

anonymous enum

Enumerator:

  TRIGGER_IF_BROKEN | This handler wants packets even with errors.
  TRIGGER_EMPTY | This handler wants only empty packets.
  TRIGGER_SUPPRESSED | This reflex is currently suppressed.
  TRIGGER_RESERVED3 | Reserved for future use; should not be set or read.
  TRIGGER_RESERVED4 | Reserved for future use; should not be set or read.
  TRIGGER_RESERVED5 | Reserved for future use; should not be set or read.
  TRIGGER_RESERVED6 | Reserved for future use; should not be set or read.
  TRIGGER_RESERVED7 | Reserved for future use; should not be set or read.
  TRIGGER_NORTH | Trigger if packet came from NORTH.
  TRIGGER_SOUTH | Trigger if packet came from SOUTH.
  TRIGGER_EAST | Trigger if packet came from EAST.
  TRIGGER_WEST | Trigger if packet came from WEST.
  TRIGGER_SPINE | Trigger if packet reaches the Spine (from any face).
  TRIGGER_MEMORY | Trigger if packet came from working memory.
  TRIGGER_BRAIN | Trigger if packet reaches the Brain (from Spine or memory).

## Member Function Documentation

bool SFBReactor::canTrigger | ( |  | ) |

Check if it is possible to trigger reflexes on a packet at this time.

It is possible to trigger reflexes on a packet when already inside a packet handler, but only a limited amount of such 'reflex nesting' is allowed.

Returns:
  `true` if a trigger() call will actually attempt to find and execute an appropriate packet handler; `false` if the max reflex nesting limit has been reached.

bool SFBReactor::inHandler | ( |  | ) |

Are we currently executing inside a packet handler function?

Returns:
  `true` if we are in (or were called directly or indirectly) from a packet handler; `false` if not (which, at sketch level, most commonly means in (code called from) setup(), loop(), or an alarm handler).

void SFBReactor::otherwise | ( | PacketHandler | pfunc,
|  | int | partitions = `TRIGGER_BRAIN`,
|  | bool | allowBroken = `false` |
| ) |  |  |

Add a 'catch-all' handler.

void SFBReactor::reflex | ( | const char | type,
|  | PacketHandler | pfunc,
|  | int | partitions = `TRIGGER_SPINE`,
|  | bool | ifBroken = `false` |
| ) |  |  |

Create a reflex association between a particular character type, and a particular PacketHandler function pfunc.

Optionally, one may specify which partition(s) the reflex should be created within; by default reflexes are created in the spine (which is searched after the individual faces, but before the brain). Also optionally, one may specify that pfunc should be invoked on packets even ifBroken, where 'broken' means the packet had some kind of error in transmission or receipt; by default broken packets are not passed to pfunc.

Parameters:

  | type | The byte value to trigger the reflex on. Can be any of the 230 possible byte value excluding the uppercase alphabetics (i.e., anything that is NOT 'A'-'Z'), because those are reserved for core software reflexes.
  | pfunc | The 'packet handler' function to invoke when a type packet is dispatched (in any of the partitions, if supplied). pfunc is a pointer to a function taking a `u8*` argument -- the packet to handle -- and returning `void`.

Blinks:
  E_API_BAD_REFLEX If type is 'A'..'Z'.

Blinks:
  E_API_REFLEX_FULL If enough reflexes have been defined that the 'casual reflex table' has run out of room. (See reflexes() for how to fix this problem if it occurs.)

Examples:
  blinkySync.cpp, eeprom1.cpp, eeprom3.cpp, fifthdirection.cpp, hallucination.cpp, i2cEeprom.cpp, netled.cpp, pingpong.cpp, pingpong2.cpp, profile2.cpp, profile3.cpp, qled1.cpp, reorder.cpp, sdcard2.cpp, sdcard3.cpp, speed2.cpp, speed3.cpp, speed4.cpp, trigger.cpp, zformat1.cpp, zformat2.cpp, and zformat3.cpp.

u8 SFBReactor::reflexes | ( | const PacketHandler * | table,
|  | int | length |
| ) |  |  |

Make an array of PacketHandler's available for use as reflex handlers.

To conserve base RAM usage, the core software allocates only a small table of pointers to packet-handling functions. If a sketch has more than MAX_CASUAL_REFLEXES packet handlers, the sketch is liable to trip the E_API_REFLEX_FULL blink code. To avoid that, the sketch makes a table of packet handlers, and calls this method to tell the core software about it. After that, the core software will refer to that table whenever a reflex is created mentioning one of the packet handlers in that table.

Example:

         void handleTypeA(u8 * packet) { ..respond to 'a' packets.. }
         void handleTypeE(u8 * packet) { ..respond to 'e' packets.. }
         void handleTypeI(u8 * packet) { ..respond to 'i' packets.. }
         void handleTypeO(u8 * packet) { ..respond to 'o' packets.. }
         void handleTypeU(u8 * packet) { ..respond to 'u' packets.. }
         void handleTypeY(u8 * packet) { ..respond to 'y' packets.. }

         // Getting to be a lot of handlers -- let's make a handler table for them
         const PacketHandler myHandlers[] = { // Note the 'const' -- important!  Makes the table go into flash
           handleTypeO,   // Note that the order handlers are
           handleTypeY,   // listed in a table is _not_ important
           handleTypeI,
           handleTypeA,
           handleTypeE,
           handleTypeU
         };

         void setup() {
           // Tell the core about my table, using the 'array size trick' to compute the length of my
           // table (the number of elements in any array is the array's total size in bytes divided by
           // the size in bytes of one array element, say, element[0]).
           Body.reflexes(myHandlers,sizeof(myHandlers)/sizeof(myHandlers[0]));

           // Note we still have to create each reflex!
           Body.reflex('a',handleTypeA);
           Body.reflex('e',handleTypeE);
           Body.reflex('i',handleTypeI);
           Body.reflex('o',handleTypeO);
           Body.reflex('u',handleTypeU);
           Body.reflex('y',handleTypeY);
         }

         void loop() { ..whatever.. }

void SFBReactor::trigger | ( | u8 * | packet,
|  | u8 | face |
| ) |  |  |

Attempt to trigger reflexes on packet, as though it had arrived on face.

Note that if calls on this method are nested within active packet handlers, the triggering may or may not occur, depending on the depth of nesting. If this is a problem, a sketch should check canTrigger() first to determine if another level of reflex nesting is possible.

Note that the core software performs no locking of data structures nor any enforcement of mutual exclusion or critical sections. If a sketch's packet handlers are not prepared to be reentered recursively, then this method should only be called from the `loop()` method, and never be called from inside any packet handler.

If canTrigger() is `false`, this method invokes no packet handlers.

Blinks:
  E_API_INVALID_PACKET if packet is null or invalid

Examples:
  hallucination.cpp, and trigger.cpp.

The documentation for this class was generated from the following files:

- src/include/SFBReactor.h
- src/components/library/SFBReactor.cpp