simpleSA/marker.cpp

305 lines
8.2 KiB
C++
Raw Permalink Normal View History

2020-08-16 02:03:43 +08:00
/*
* "Marker.cpp" Contains the code for the "Marker" class functions
*/
#include "marker.h" // Class definition
2020-08-16 02:03:43 +08:00
/*
* There are two constructors; the first simply creates an uninitialized
* object, and the second one fills in the address of the display object,
* the address of the marker's sprite and sets the marker's number. The
* "Init" function actually does the work.
*/
Marker::Marker () {} // Create an uninitialized object
Marker::Marker ( TFT_eSprite* spr, uint8_t marker )
{
Init ( spr, marker );
}
/*
* The "Init" function does all the work of the real constructor but can also
* be called to initialized a previously uninitialized object.
*/
void Marker::Init ( TFT_eSprite* spr, uint8_t marker )
{
/*
* Create our "sprite" and set it up. The actual sprites are created in the main
* program. It would make more sense to creat them in here, but I haven't figured
* out how to do that without causing crashes or other goofy behaviors.
*/
_sprite = spr; // Pointer to our sprite object
_sprite->setAttribute ( PSRAM_ENABLE, false ); // Don't use PSRAM on the WROVERs
_sprite->createSprite ( MARKER_SPRITE_WIDTH, MARKER_SPRITE_HEIGHT ); // Set the size
/*
* Set some default conditions for the time being:
*/
_index = marker - 1; // Save marker number
_enabled = false; // Turn it off for now
_status = 0; // White, disabled & invisible
_x = 0; // No real position yet
_y = 0;
_frequency = 0; // Don't know the frequency
_mode = MKR_PEAK; // Assume peak frequency mode
/*
* Set the pivot point for the marker - this is the point used when pushing
*/
_sprite->setPivot ( X_MARKER_OFFSET, Y_MARKER_OFFSET );
}
/*
* "Paint" Remembers the "x"and "y" coordinates and sends the marker to the display.
* Note x and y are relative to the target sprite
*/
void Marker::Paint ( TFT_eSprite *target, uint16_t x, uint16_t y )
{
if ( _enabled )
{
_x = x + 1; // Remember location
_y = y;
target->setPivot ( _x, _y ); // Set pivot point in target.
// Push rotated checks the bounds of
// the target sprite
_sprite->pushRotated ( target, 0, BLACK ); // Send the sprite to the target sprite
}
else // Not enabled
return; // Do nothing
}
/*
* Set or retreive the mode for the marker.
*/
void Marker::Mode ( uint8_t mode )
{
_mode = mode; // Simple enough!
}
uint8_t Marker::Mode ()
{
return _mode; // Also simple!
}
/*
* The next three functions set or clear the "_enabled" indicator. There are two
* versions of "Enable"; the first simply marks the marker as enabled and the
* second enables the marker and sets the mode all at once.
*
* "Toggle" toggles the enabled/disabled status.
*
* These functions also manipulate the "MKR_ACTIVE" bit in the "_status" byte.
*/
void Marker::Enable () // Enable it
{
_enabled = true;
_status |= MKR_ACTIVE; // In the "_status" byte also
}
void Marker::Enable ( uint8_t mode ) // Enable & set mode all at once
{
Mode ( mode ); // Set the mode
Enable (); // and enable the marker
}
void Marker::Disable () // Disable it
{
_enabled = false;
_status &= ~MKR_ACTIVE; // In the "_status" byte also
}
void Marker::Toggle () // Toggle enabled/disabled status
{
_enabled = !_enabled;
_status ^= MKR_ACTIVE; // In the "_status" byte also
}
/*
* "isEnabled" returns "true" if the marker is enabled; "false" if not.
*/
bool Marker::isEnabled () // Request enabled/disabled status
{
return _enabled;
}
/*
* Set or get the marker's current frequency.
*/
void Marker::Frequency ( uint32_t freq ) // Set the marker's frequency
{
_frequency = freq;
}
uint32_t Marker::Frequency () // Get the frequency
{
return _frequency;
}
uint8_t Marker::Index () // Get marker's index
{
return _index;
}
/*
* This version of "Status" simply returns the current "_status" byte, which is updated
* whenever a new color for the marker is specified or the enabled/disabled changes.
*/
uint8_t Marker::Status () // Return the "_status" byte
{
return _status;
}
/*
* This version of "Status" is used to set the "_status" byte. Note, that we don't
* check for a legitimate color choice here as the expectation is that this capability
* is only used by the main program when the marker statuses saved in flash memory
* are recalled at startup.
*/
void Marker::Status ( uint8_t status) // Set the status byte
{
_color = _colors[status & MKR_COLOR];
Color ( _color );
if ( status & MKR_ACTIVE ) // Enable it?
Enable (); // Yes, do it
else // Otherwise
Disable (); // Turn it off
}
/*
* This version of "Color" (do I need an alternate version named "Colour" for the
* Brits?) simply returns the 16 bit color assigned to the marker.
*/
uint16_t Marker::Color () // Returns the marker's color
{
return _color;
}
/*
* This version of "Color" is used by the serial command handler and the touch screen
* menu system to specify the color for the marker.
*
* There are only six colors allowed. The number is based on the fact that the touch
* screen menu can only display that many choices at once. The legal colors are defined
* in the "_colors" array in the header file.
*
* The function checks to see if the specified color is in the list and if so, not only
* sets the "_color" variable, but also updates the "_status" byte.
*/
bool Marker::Color ( uint16_t color ) // Sets the marker's color
{
/*
* The "markerBitmap" shows where in the "sprite" the pixels should be of
* the specified color (1) and where the background color (0) should be used.
*
* Using the bitmap, we build the "sprite" using the specified color.
*/
const uint8_t markerBitmap[] =
{
0xFE, 0xEE, 0xCE, 0xEE, 0xEE, 0xEE, 0xC6, 0x7C, 0X38, 0x10, // Marker 1
0xFE, 0xC6, 0xBA, 0xFA, 0xC6, 0xBE, 0x82, 0x7C, 0x38, 0x10, // Marker 2
0xFE, 0xC6, 0xBA, 0xE6, 0xFA, 0xBA, 0xC6, 0x7C, 0x38, 0x10, // Marker 3
0xFE, 0xF6, 0xE6, 0xD6, 0xB6, 0xB6, 0x82, 0x74, 0x38, 0x10, // Marker 4
};
int line; // Which horizontal line we're painting
int column; // and which column
int colorIx; // Loop index
uint8_t bits; // One byte from the marker definition
bool returnCode = false; // Assume bad color specification
/*
* The first thing we do is to compare the requested color to the legitimate ones
* and if we don't find a match, return a "false" indication.
*/
for ( colorIx = 0; colorIx < MKR_COLOR_COUNT; colorIx++ )
if ( color == _colors[colorIx] ) // Found a match?
{
returnCode = true; // Set good return code
break; // No need to look further
}
if ( !returnCode ) // If no match found
return false; // Return "false"
_color = color; // It's a legal color, so save it
_status = _status & ~MKR_COLOR; // Clear the previous color
_status = _status | colorIx; // Set the new one
/*
* Next, we re-paint our sprite in the new color.
*/
for ( line = 0; line < MARKER_HEIGHT; line++ ) // Paint one line at a time
{
bits = markerBitmap[_index * MARKER_HEIGHT + line]; // Get bitmap of the next line
for ( column = 0; column < MARKER_WIDTH; column++ ) // horizontally left to right
{
if ( bits & 0x80 ) // Next pixel turned on?
_sprite->drawPixel ( column, line, SwapBytes ( _color )); // Yes, use specified color
else
_sprite->drawPixel ( column, line, BACKGROUND );// Use display background color
bits <<= 1; // Shift the bitmap byte one place left
}
}
return true; // Good return code
}
/*
* "SwapBytes" was added in Version 2.9. Bodmer did something in the TFT_eSPI library
* (version 2.2.5 and later) that makes it necessary to swap the bytes in the color
* word when using rotated sprites (as we do here).
*/
uint16_t Marker::SwapBytes ( uint16_t color)
{
uint16_t low = ( color & 0x00FF ) << 8;
uint16_t high = ( color & 0xFF00 ) >> 8;
uint16_t swap = low | high;
return swap;
}