From 5a11ca3a354679f47e9355cd68b9fdd0da1aae57 Mon Sep 17 00:00:00 2001 From: David Zemon Date: Thu, 7 Apr 2016 18:24:31 -0500 Subject: [PATCH] [#53] PropWare-ify VGA code --- Examples/PropWare_VGAText/VGAText_Demo.cpp | 32 ++- PropWare/CMakeLists.txt | 1 - PropWare/hmi/output/video/vga.h | 31 ++- PropWare/hmi/output/video/vgatext.cpp | 231 ---------------- PropWare/hmi/output/video/vgatext.h | 301 ++++++++++++++------- PropWare/utility/utility.h | 9 + 6 files changed, 250 insertions(+), 355 deletions(-) delete mode 100644 PropWare/hmi/output/video/vgatext.cpp diff --git a/Examples/PropWare_VGAText/VGAText_Demo.cpp b/Examples/PropWare_VGAText/VGAText_Demo.cpp index 46c91937..9801db53 100644 --- a/Examples/PropWare_VGAText/VGAText_Demo.cpp +++ b/Examples/PropWare_VGAText/VGAText_Demo.cpp @@ -1,20 +1,24 @@ #include +#include int main() { - PropWare::VGAText Text; - int i; + PropWare::VGAText vgaText; + PropWare::Printer vgaPrinter(vgaText); + vgaText.start(8); - Text.start(8); - Text.str("\r VGA Text Demo...\r\r\x0C\x05 OBJ and VAR require only 5.0KB \x0C\x01"); - for (i = 0; i < 14; i++) { - Text.out(' '); - } - for (i = 0x0E; i <= 0xFF; i++) { - Text.out(i); - } - Text.str("\x0C\x06 Uses internal ROM font \x0C\x02"); - for (;;) { - Text.str("\x0A\x0C\x0B\x0E"); - Text.hex(i++, 8); + vgaPrinter << "\r VGA Text Demo...\r\r\x0C\x05 OBJ and VAR require only 5.0KB \x0C\x01"; + + for (char i = 0; i < 14; i++) + vgaPrinter << ' '; + + for (char i = 0x0E; i <= 0xFF; i++) + vgaPrinter << i; + + vgaPrinter << "\x0C\x06 Uses internal ROM font \x0C\x02"; + + uint16_t i = 0xFF; + while (1) { + vgaPrinter << "\x0A\x0C\x0B\x0E"; + vgaPrinter.printf("0x04X ", i++); } } diff --git a/PropWare/CMakeLists.txt b/PropWare/CMakeLists.txt index a06634e7..0acc4140 100644 --- a/PropWare/CMakeLists.txt +++ b/PropWare/CMakeLists.txt @@ -19,7 +19,6 @@ set(PROPWARE_SOURCES ${CMAKE_CURRENT_LIST_DIR}/hmi/output/synchronousprinter.cpp ${CMAKE_CURRENT_LIST_DIR}/hmi/output/synchronousprinter.h ${CMAKE_CURRENT_LIST_DIR}/hmi/output/ws2812.h - ${CMAKE_CURRENT_LIST_DIR}/hmi/output/video/vgatext.cpp ${CMAKE_CURRENT_LIST_DIR}/hmi/output/video/vgatext.h ${CMAKE_CURRENT_LIST_DIR}/hmi/output/video/vga.h ${CMAKE_CURRENT_LIST_DIR}/hmi/output/video/vga_driver.S diff --git a/PropWare/hmi/output/video/vga.h b/PropWare/hmi/output/video/vga.h index 67080041..cce021c9 100644 --- a/PropWare/hmi/output/video/vga.h +++ b/PropWare/hmi/output/video/vga.h @@ -1,10 +1,26 @@ /** - * *************************************** - * * VGA Driver v1.1 * - * * Author: Chip Gracey * - * * Copyright (c) 2006 Parallax, Inc. * - * * See end of file for terms of use. * - * *************************************** + * @file vga.h + * @author Chip Gracey + * + * @copyright + * The MIT License (MIT)
+ *
Copyright (c) 2006 Parallax, Inc.
+ *
Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions:
+ *
The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software.
+ *
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * * v1.0 - 01 May 2006 - original version * v1.1 - 15 May 2006 - pixel tile size can now be 16 x 32 to enable more efficient * character displays utilizing the internal font - see 'vga_mode' @@ -21,6 +37,9 @@ extern int _VGADriverStartCog (void *arg); namespace PropWare { +/** + * VGA Driver v1.1 + */ class VGA { public: /* diff --git a/PropWare/hmi/output/video/vgatext.cpp b/PropWare/hmi/output/video/vgatext.cpp deleted file mode 100644 index cf86ba62..00000000 --- a/PropWare/hmi/output/video/vgatext.cpp +++ /dev/null @@ -1,231 +0,0 @@ -// *************************************** -// * VGA Text 32x15 v1.0 * -// * Author: Chip Gracey * -// * Copyright (c) 2006 Parallax, Inc. * -// * See end of file for terms of use. * -// *************************************** - -#include -#include - -#define INLINE__ static inline -#define PostEffect__(X, Y) __extension__({ int32_t tmp__ = (X); (X) = (Y); tmp__; }) - -namespace PropWare { - -static inline int32_t Rotl__ (uint32_t a, uint32_t b) { - return (a << b) | (a >> (32 - b)); -} - -static inline int32_t Rotr__ (uint32_t a, uint32_t b) { - return (a >> b) | (a << (32 - b)); -} - -static inline int32_t Between__ (int32_t x, int32_t a, int32_t b) { - if (a <= b) - return x >= a && x <= b; - return x >= b && x <= a; -} - -static inline int32_t Lookup__ (int32_t x, int32_t b, int32_t a[], int32_t n) { - int32_t i = (x) - (b); - return ((unsigned) i >= n) ? 0 : (a)[i]; -} - -/** - * Default color palette - */ -static uint8_t palette[] = { - 0x3f, 0x01, // 0 white / dark blue - 0x3c, 0x14, // 1 yellow / brown - 0x22, 0x00, // 2 magenta / black - 0x15, 0x3f, // 3 grey / white - 0x0f, 0x05, // 4 cyan / dark cyan - 0x08, 0x2e, // 5 green / gray-green - 0x10, 0x35, // 6 red / pink - 0x0f, 0x03 // 7 cyan / blue -}; - -int32_t VGAText::start (int32_t basepin) { - int32_t okay = 0; - - setcolors(palette); - out(0); - - vga.params.vga_status = 0; // 0/1/2 = off/visible/invisible read-only - vga.params.vga_enable = 1; // 0/non-0 = off/on write-only - vga.params.vga_pins = basepin | 0x7; // %pppttt = pins write-only - vga.params.vga_mode = 0b1000; // %tihv = tile,interlace,hpol,vpol write-only - vga.params.vga_screen = (int32_t) &screen[0]; // pointer to screen (words) write-only - vga.params.vga_colors = (int32_t) &colors[0]; // pointer to colors (longs) write-only - vga.params.vga_ht = cols; // horizontal tiles write-only - vga.params.vga_vt = rows; // vertical tiles write-only - vga.params.vga_hx = 1; // horizontal tile expansion write-only - vga.params.vga_vx = 1; // vertical tile expansion write-only - vga.params.vga_ho = 0; // horizontal offset write-only - vga.params.vga_vo = 0; // vertical offset write-only - vga.params.vga_hd = 512; // horizontal display ticks write-only - vga.params.vga_hf = 10; // horizontal front porch ticks write-only - vga.params.vga_hs = 75; // horizontal sync ticks write-only - vga.params.vga_hb = 43; // horizontal back porch ticks write-only - vga.params.vga_vd = 480; // vertical display lines write-only - vga.params.vga_vf = 11; // vertical front porch lines write-only - vga.params.vga_vs = 2; // vertical sync lines write-only - vga.params.vga_vb = 31; // vertical back porch lines write-only - vga.params.vga_rate = CLKFREQ >> 2; // tick rate (Hz) write-only - - okay = vga.start(); - - return okay; -} - -void VGAText::stop (void) { - vga.stop(); -} - -void VGAText::str (const char *stringptr) { - while (*stringptr != 0) { - out(*stringptr++); - } -} - -void VGAText::dec (int32_t value) { - int32_t i, idx; - int32_t result = 0; - - if (value < 0) { - value = -value; - out('-'); - } - i = 1000000000; - for (idx = 1; idx <= 10; idx = idx + 1) { - if (value >= i) { - out(((value / i) + '0')); - value = value % i; - result = -1; - } else { - if ((result) || (i == 1)) { - out('0'); - } - } - i = i / 10; - } -} - -void VGAText::hex (int32_t value, int32_t digits) { - int32_t idx; - int32_t limit = digits; - static int32_t look__0003[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - - value = value << ((8 - digits) << 2); - for (idx = 1; idx <= limit; idx = idx + 1) { - out(Lookup__(((value = Rotl__(value, 4)) & 0xf), 0, look__0003, 16)); - } -} - -void VGAText::bin (int32_t value, int32_t digits) { - int32_t idx; - int32_t limit = digits; - - value = value << (32 - digits); - for (idx = 1; idx <= limit; idx = idx + 1) { - out((((value = Rotl__(value, 1)) & 0x1) + '0')); - } -} - -int32_t VGAText::out (char c) { - int32_t result = 0; - - if (flag == 0) { - if (c == 0) { - int32_t fill; - uint16_t *ptr = (uint16_t *) &screen[0]; - uint16_t val = 0x220; - for (fill = screensize; fill > 0; --fill) { - *ptr++ = val; - } - col = (row = 0); - } else if (c == 1) { - col = (row = 0); - } else if (c == 8) { - if (col) { - (col--); - } - } else if (c == 9) { - do { - print(' '); - } while (col & 0x7); - } else if (Between__(c, 10, 12)) { - flag = c; - return result; - } else if (c == 13) { - newline(); - } else if (1) { - print(c); - } - } else if (flag == 10) { - col = c % cols; - } else if (flag == 11) { - row = c % rows; - } else if (flag == 12) { - color = c & 0x7; - } - flag = 0; - return result; -} - -void VGAText::setcolors (uint8_t *colorptr) { - int32_t i, fore, back; - - for (i = 0; i <= 7; i = i + 1) { - fore = (colorptr)[(i << 1)] << 2; - back = (colorptr)[((i << 1) + 1)] << 2; - colors[(i << 1)] = (((fore << 24) + (back << 16)) + (fore << 8)) + back; - colors[((i << 1) + 1)] = (((fore << 24) + (fore << 16)) + (back << 8)) + back; - } -} - -void VGAText::print (int32_t c) { - screen[((row * cols) + col)] = ((((color << 1) + (c & 0x1)) << 10) + 512) + (c & 0xfe); - if ((++col) == cols) { - newline(); - } -} - -void VGAText::newline (void) { - col = 0; - if ((++row) == rows) { - (row--); - // scroll lines - memmove((void *) &screen[0], (void *) &screen[cols], 2 * (lastrow)); - // clear new line - { - int32_t fill; - uint16_t *ptr = (uint16_t *) &screen[lastrow]; - uint16_t val = 0x220; - for (fill = cols; fill > 0; --fill) { - *ptr++ = val; - } - }; - } -} - -} - -/* - ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ TERMS OF USE: MIT License │ - ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ - │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ - │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ - │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ - │is furnished to do so, subject to the following conditions: │ - │ │ - │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ - │ │ - │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ - │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ - │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ - │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ - └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - */ diff --git a/PropWare/hmi/output/video/vgatext.h b/PropWare/hmi/output/video/vgatext.h index 1c8de36b..1c99cc43 100644 --- a/PropWare/hmi/output/video/vgatext.h +++ b/PropWare/hmi/output/video/vgatext.h @@ -1,113 +1,208 @@ -// *************************************** -// * VGA Text 32x15 v1.0 * -// * Author: Chip Gracey * -// * Copyright (c) 2006 Parallax, Inc. * -// * See end of file for terms of use. * -// *************************************** +/** + * @file vgatext.h + * @author Chip Gracey + * + * @copyright + * The MIT License (MIT)
+ *
Copyright (c) 2006 Parallax, Inc.
+ *
Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions:
+ *
The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software.
+ *
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ #pragma once #include +#include +#include namespace PropWare { -class VGAText { -public: - static const int cols = 32; - static const int rows = 15; - static const int screensize = (cols * rows); - static const int lastrow = (screensize - cols); - - /** - * Start terminal - starts a cog - * returns false if no cog available - * - * requires at least 80MHz system clock - */ - int32_t start(int32_t basepin); - - /** - * Stop terminal - frees a cog - */ - void stop(); - - /** - * Print a zero-terminated string - */ - void str(const char *stringptr); - - /** - * Print a decimal number - */ - void dec(int32_t value); - - /** - * Print a hexadecimal number - */ - void hex(int32_t value, int32_t digits); - - /** - * Print a binary number - */ - void bin(int32_t value, int32_t digits); - - /** - * Output a character - * - * $00 = clear screen - * $01 = home - * $08 = backspace - * $09 = tab (8 spaces per) - * $0A = set X position (X follows) - * $0B = set Y position (Y follows) - * $0C = set color (color follows) - * $0D = return - * others = printable characters - */ - int32_t out(char c); - - /** - * Override default color palette - * - * colorptr must point to a list of up to 8 colors - * arranged as follows (where r, g, b are 0..3): - * - * fore back - * ------------ - * palette byte %%rgb, %%rgb 'color 0 - * byte %%rgb, %%rgb 'color 1 - * byte %%rgb, %%rgb 'color 2 - */ - void setcolors(uint8_t *colorptr); - -private: - VGA vga; - - volatile int32_t col, row, color, flag; - volatile int32_t colors[16]; - volatile uint16_t screen[480]; - - void print(int32_t c); - - void newline(); +class VGAText : public PrintCapable { + public: + static const int COLUMNS = 32; + static const int ROWS = 15; + static const int SCREEN_SIZE = (COLUMNS * ROWS); + static const int LAST_ROW = (SCREEN_SIZE - COLUMNS); + + /** + * Start terminal - starts a cog + * returns false if no cog available + * + * requires at least 80MHz system clock + */ + int32_t start(const int32_t basepin) { + // Default color palette + static uint8_t palette[] = { + 0x3f, 0x01, // 0 white / dark blue + 0x3c, 0x14, // 1 yellow / brown + 0x22, 0x00, // 2 magenta / black + 0x15, 0x3f, // 3 grey / white + 0x0f, 0x05, // 4 cyan / dark cyan + 0x08, 0x2e, // 5 green / gray-green + 0x10, 0x35, // 6 red / pink + 0x0f, 0x03 // 7 cyan / blue + }; + + this->set_colors(palette); + this->put_char(0); + + this->m_vga.params.vga_status = 0; // 0/1/2 = off/visible/invisible read-only + this->m_vga.params.vga_enable = 1; // 0/non-0 = off/on write-only + this->m_vga.params.vga_pins = basepin | 0x7; // %pppttt = pins write-only + this->m_vga.params.vga_mode = 0b1000; // %tihv = tile,interlace,hpol,vpol write-only + this->m_vga.params.vga_screen = (uint32_t) &m_screen[0]; // pointer to screen (words) write-only + this->m_vga.params.vga_colors = (uint32_t) &m_colors[0]; // pointer to colors (longs) write-only + this->m_vga.params.vga_ht = COLUMNS; // horizontal tiles write-only + this->m_vga.params.vga_vt = ROWS; // vertical tiles write-only + this->m_vga.params.vga_hx = 1; // horizontal tile expansion write-only + this->m_vga.params.vga_vx = 1; // vertical tile expansion write-only + this->m_vga.params.vga_ho = 0; // horizontal offset write-only + this->m_vga.params.vga_vo = 0; // vertical offset write-only + this->m_vga.params.vga_hd = 512; // horizontal display ticks write-only + this->m_vga.params.vga_hf = 10; // horizontal front porch ticks write-only + this->m_vga.params.vga_hs = 75; // horizontal sync ticks write-only + this->m_vga.params.vga_hb = 43; // horizontal back porch ticks write-only + this->m_vga.params.vga_vd = 480; // vertical display lines write-only + this->m_vga.params.vga_vf = 11; // vertical front porch lines write-only + this->m_vga.params.vga_vs = 2; // vertical sync lines write-only + this->m_vga.params.vga_vb = 31; // vertical back porch lines write-only + this->m_vga.params.vga_rate = CLKFREQ >> 2; // tick rate (Hz) write-only + + return this->m_vga.start(); + } + + /** + * Stop terminal - frees a cog + */ + void stop() { + this->m_vga.stop(); + } + + /** + * Print a zero-terminated string + */ + void puts(const char *string) { + while (*string) + this->put_char(*string++); + } + + /** + * Output a character + * + * $00 = clear screen + * $01 = home + * $08 = backspace + * $09 = tab (8 spaces per) + * $0A = set X position (X follows) + * $0B = set Y position (Y follows) + * $0C = set color (color follows) + * $0D = return + * others = printable characters + */ + void put_char(const char c) { + if (this->m_flag == 0) { + if (c == 0) { + int32_t fill; + uint16_t *ptr = (uint16_t *) &this->m_screen[0]; + uint16_t val = 0x220; + for (fill = SCREEN_SIZE; fill > 0; --fill) { + *ptr++ = val; + } + this->m_col = (this->m_row = 0); + } else if (c == 1) + this->m_col = (this->m_row = 0); + else if (c == 8) { + if (this->m_col) + this->m_col--; + } else if (c == 9) + do { + print(' '); + } while (this->m_col & 0x7); + else if (Utility::between(c, 10, 12)) { + this->m_flag = c; + return; + } else if (c == 13) + newline(); + else + print(c); + } else if (this->m_flag == 10) { + this->m_col = c % COLUMNS; + } else if (this->m_flag == 11) { + this->m_row = c % ROWS; + } else if (this->m_flag == 12) { + this->m_color = c & 0x7; + } + this->m_flag = 0; + } + + /** + * Override default color palette + * + * colorptr must point to a list of up to 8 colors + * arranged as follows (where r, g, b are 0..3): + * + * fore back + * ------------ + * palette byte %%rgb, %%rgb 'color 0 + * byte %%rgb, %%rgb 'color 1 + * byte %%rgb, %%rgb 'color 2 + */ + void set_colors(const uint8_t *colorptr) { + int32_t i, fore, back; + + for (i = 0; i <= 7; i = i + 1) { + fore = (colorptr)[(i << 1)] << 2; + back = (colorptr)[((i << 1) + 1)] << 2; + this->m_colors[(i << 1)] = (((fore << 24) + (back << 16)) + (fore << 8)) + back; + this->m_colors[((i << 1) + 1)] = (((fore << 24) + (fore << 16)) + (back << 8)) + back; + } + } + + private: + void print(int32_t c) { + m_screen[((m_row * COLUMNS) + m_col)] = ((((m_color << 1) + (c & 0x1)) << 10) + 512) + (c & 0xfe); + if ((++m_col) == COLUMNS) { + newline(); + } + } + + void newline() { + this->m_col = 0; + if ((++this->m_row) == ROWS) { + (this->m_row--); + // scroll lines + memmove((void *) &this->m_screen[0], (void *) &this->m_screen[COLUMNS], (size_t) (2 * (LAST_ROW))); + // clear new line + { + int32_t fill; + uint16_t *ptr = (uint16_t *) &this->m_screen[LAST_ROW]; + uint16_t val = 0x220; + for (fill = COLUMNS; fill > 0; --fill) { + *ptr++ = val; + } + }; + } + } + + private: + VGA m_vga; + + volatile int32_t m_col, m_row, m_color, m_flag; + volatile int32_t m_colors[16]; + volatile uint16_t m_screen[480]; }; } - -/* - ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ TERMS OF USE: MIT License │ - ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ - │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ - │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ - │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ - │is furnished to do so, subject to the following conditions: │ - │ │ - │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ - │ │ - │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ - │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ - │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ - │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ - └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - */ diff --git a/PropWare/utility/utility.h b/PropWare/utility/utility.h index 0fe61500..d3e41c25 100644 --- a/PropWare/utility/utility.h +++ b/PropWare/utility/utility.h @@ -270,6 +270,15 @@ class Utility { x &= ~bit; } + /** + * @brief Determine if a number is between two others + */ + static bool between(int x, int a, int b) { + if (a <= b) + return x >= a && x <= b; + return x >= b && x <= a; + } + private: /** * @brief Static Utility class should never be instantiated. Call methods with code such as