diff --git a/SCTVcode/SCTVcode.ino b/SCTVcode/SCTVcode.ino index 98d4287..8c1ad4f 100644 --- a/SCTVcode/SCTVcode.ino +++ b/SCTVcode/SCTVcode.ino @@ -17,23 +17,23 @@ // V 1.00 4/07/08 DF Initial release // V 2.00 1/27/16 DF working on Arduino C version // 1/29/16 DF Code compiles, DoSeg works as to timing; actual circles await a PC board -// 2/13/16 DF It can draw a circle, but nothing else. +// 2/13/16 DF It can draw a circle, but nothing else. // 2/16/16 DF Text and menus work (still a centering bug), doing RTC // V 3.00 11/17/19 DF Converting to Teensy 3.6, software circle generator // V 3.10 12/23/19 DF It's starting to work, still need to fix centering bug // V 3.20 12/26/19 DF Adding software centering, prelude to Pong capability // V 3.21 09/04/21 DF Changed DAC scale in draw code to handle new position system // Pong is incorporated into drawlist, needs scoring work -// V 3.22 09/05/21 DF Pong has scoring, working on hands clock. Done. Had Shape bug. +// V 3.22 09/05/21 DF Pong has scoring, working on hands clock. Done. Had Shape bug. // V 3.30 09/09/21 DF Changing screen field to 2560, add a 0 to all x,y values, change byte to int // V 0.4.0 09/10/21 DF Removed middle, fixed weekday, tweaked Pong // V 0.4.1 09/11/21 DF Fixed WDayStr length, leading zeroes, doSeg // V 0.4.2 09/12/21 DF Added haikus, Tetris objects, split into files // V 0.4.3 09/24/21 DF Improved Tetris // V 0.5.0 09/29/21 DF Adding GPS over USB for SCTV-C -// V 0.5.1 09/30/21 DF GPS works, can be plugged and unplugged -// V 0.5.2 10/01/21 DF Improved Pong end of game, added ball delay -// V 0.5.3 11/23/21 DF Added 50 Hz menu option for our worldwide friends +// V 0.5.1 09/30/21 DF GPS works, can be plugged and unplugged +// V 0.5.2 10/01/21 DF Improved Pong end of game, added ball delay +// V 0.5.3 11/23/21 DF Added 50 Hz menu option for our worldwide friends // V 1.0.0 11/30/21 DF Made screensaver bigger, issued as a release // V 1.0.1 12/20/21 DF Made the locale data stored in the RTC chip // V 1.0.2 01/21/22 DF Fixed brightness on 0 via stride, moved tails on 6,9 @@ -47,28 +47,28 @@ char versionNo[] = "Version 1.0.2\n"; //---------------------- Description ----------------------- // Target CPU: Teensy 3.6 -// 32 bit ARM +// 32 bit ARM // Clock speed: 180 MHz // Basic description // The scope clock uses circles to display the time. -// The circle generator is the Teensy's built-in dual DAC. -// sin and cos lookup tables allow a DAC update rate of ~1 MHz. -// Lines are drawn with the length calculated using Pythagoras when needed (not horiz or vert). -// -// The coordinate system is (0,0) at center of screen. -// The display scaling is .001" per unit, with active area of 2500x2500 units. -// All coordinates are 32 bit integers. - -// The display timing has been tweaked to make clean circles. There -// is a bit of extra delay time provided for the CRT beam to move while blanked, -// which allows the use of simple low-slew-rate deflection amplifiers. +// The circle generator is the Teensy's built-in dual DAC. +// sin and cos lookup tables allow a DAC update rate of ~1 MHz. +// Lines are drawn with the length calculated using Pythagoras when needed (not horiz or vert). +// +// The coordinate system is (0,0) at center of screen. +// The display scaling is .001" per unit, with active area of 2500x2500 units. +// All coordinates are 32 bit integers. + +// The display timing has been tweaked to make clean circles. There +// is a bit of extra delay time provided for the CRT beam to move while blanked, +// which allows the use of simple low-slew-rate deflection amplifiers. // // Timekeeping // -// The timebase is a DS3232 RTC chip. It's read once per display loop. -// Ther is currently no DST. +// The timebase is a DS3232 RTC chip. It's read once per display loop. +// Ther is currently no DST. // DST may be added with lookup tables based on political regions. // // Draw list @@ -98,8 +98,9 @@ char versionNo[] = "Version 1.0.2\n"; // // ---------------------------- Hardware definitions ----------------------------- +#include -#include +#include #include // I2C library #include "USBHost_t36.h" #include @@ -108,13 +109,13 @@ char versionNo[] = "Version 1.0.2\n"; // #define SCTVA // The clock chip's I2C bus address -#define DS3232_ADDRESS 0x68 +#define DS3232_ADDRESS 0x68 // Teensy 3.6 pin definitions int BlankPin = 2; // high blanks the display int encButPin = 14; // encoder button, 0 = pressed int encBPin = 15; // encoder quadrature -int encAPin = 16; +int encAPin = 16; int XPosPin = A15; // horizontal centering knob #ifdef SCTVA int YPosPin = A18; // vertical centering knob on SCTVA is in odd place @@ -128,14 +129,48 @@ int randPin = A12; // random numbers are read from the air here bool doingHand = true; // diagnostic print for drawing code // new variables for software circle drawing -float pi = 3.141592; +constexpr float pi = 3.141592; int thisX, thisY; // circle position -int i; -const int nsteps = 1024; // was 240 to be consistent with the old circle angle definition +constexpr int nsteps = 1024; // was 240 to be consistent with the old circle angle definition // the sin/cos lookup table outputs are signed ints in range from -65536 to +65536 -int sintab[nsteps]; -int costab[nsteps]; // scaled int angle lookup tables, filled in during init + +template +class Array { +public: + T data[Size]; + + using size_type = size_t; + using value_type = T; + + constexpr value_type& operator[](size_type index) { + return data[index]; + } + + constexpr const value_type& operator[](size_type index) const { + return data[index]; + } +}; + +constexpr Array generateCosTab() { + Array costab {}; + for (size_t i = 0; i < nsteps; ++i) + costab[i] = int(65536.*cos(float(i*2)*pi/float(nsteps))); + + return costab; +} + +constexpr Array generateSinTab() { + Array sintab {}; + for (size_t i = 0; i < nsteps; i++) + sintab[i] = int(65536.*sin(float(i*2)*pi/float(nsteps))); + + return sintab; +} + +// scaled int angle lookup tables +constexpr auto costab = generateCosTab(); +constexpr auto sintab = generateSinTab(); // --------------------------- RAM variables -------------------------- @@ -152,28 +187,28 @@ int xPos; // where the knob says to be int yPos; // -512 to +511 range (10 bit ADC code) // timekeeping variables -int Hr12 = 1; // 1 if 12 hour mode, 0 if 24 hour mode -int Century = 20; // century range 0-99 (not Y10K compliant!) -int Years = 21; // years range 0-99 -int Mons = 1; // months range 1-12 -int WDay = 0; // day of week, 0=Sunday -int Days = 1; // days range 1-31 -int Hrs = 0; // hours range 0-23 -int Mins = 0; // minutes range 0-59 All of these have signed math when menu modifies them! -int Secs = 0; // seconds range 0-59 -int Ticks = 0; // ticks range 0-59 (0-49 if 50 Hz) -int Jiffies = 0; // 300 Hz jiffies 0-4 or 0-5 +bool Hr12 = true; // 1 if 12 hour mode, 0 if 24 hour mode +int8_t Century = 20; // century range 0-99 (not Y10K compliant!) +int8_t Years = 21; // years range 0-99 +int8_t Mons = 1; // months range 1-12 +int8_t WDay = 0; // day of week, 0=Sunday +int8_t Days = 1; // days range 1-31 +int8_t Hrs = 0; // hours range 0-23 +int8_t Mins = 0; // minutes range 0-59 All of these have signed math when menu modifies them! +int8_t Secs = 0; // seconds range 0-59 +int8_t Ticks = 0; // ticks range 0-59 (0-49 if 50 Hz) +int8_t Jiffies = 0; // 300 Hz jiffies 0-4 or 0-5 int Blink; // increments at tick rate, use Blnkbit to blink -int HalfSec = 30; // 30 for 60 Hz or 25 for 50 Hz -unsigned int Hertz = 60; // 50 or 60 -int JifTick = 5; // 5 or 6 - jiffies per tick depends on Hz +int8_t HalfSec = 30; // 30 for 60 Hz or 25 for 50 Hz +uint8_t Hertz = 60; // 50 or 60 +int8_t JifTick = 5; // 5 or 6 - jiffies per tick depends on Hz int ScrX; // screensaver position table index 0..ScrTabL int XSaver; // current X offset of screensaver int YSaver; // current Y offset of screensaver -int DST = 0; // daylight savings, 0 or 1 hour advance -int Zone = -7; // time zone, -12 to +12 hours -int ZMins = 0; // zone minutes, 0,15,30,45 -int rtcMagic = 0x33; // magic number for verifying RTC data +bool DST = false; // daylight savings, 0 or 1 hour advance +int8_t Zone = -7; // time zone, -12 to +12 hours +int8_t ZMins = 0; // zone minutes, 0,15,30,45 +int8_t rtcMagic = 0x33; // magic number for verifying RTC data int rtcValid = 0; // set to rtcMagic when RTC data written to tell if it's trustworthy int HundrSec = 0; // hundredths of seconds, maybe not needed but GPS provides it @@ -194,7 +229,7 @@ int theClock; // which clock face to show int NItems; // how many items in menu to make hot, found by DoAList??? // Text string variables -char *StrPtr; // points to text string location +const char *StrPtr; // points to text string location char TheChr; // current character ASCII code int ChrXPos; // X position of LL corner of this character int ChrYPos; // Y position @@ -231,18 +266,20 @@ int LastO; // last octant to display // They need a real xpos and ypos specified. // A draw list is a list of items to be drawn. These comprise: -const int listend = 0; // end of list -const int text = 1; // size, zero, stringptr, xpos, ypos text item, no menu -const int menu = 2; // size, function, stringptr, xpos, ypos text item with menu -const int field = 3; // size, function, stringptr, xpos, ypos changeable field text -const int seg = 4; // size, function, segptr, xpos, ypos segment (special character) +enum class ItemType { + listend = 0, // end of list + text = 1, // size, zero, stringptr, xpos, ypos text item, no menu + menu = 2, // size, function, stringptr, xpos, ypos text item with menu + field = 3, // size, function, stringptr, xpos, ypos changeable field text + seg = 4, // size, function, segptr, xpos, ypos segment (special character) +}; // Each item of a drawlist is one of these: struct item { - int type; // see list above + ItemType type; // see list above int scale; // scale factor int func; // function to execute (mod or menu numeration) if used, 0 if not - char *string; // the string to display + const char* string; // the string to display int xpos; // where it goes, or used when calculating where it goes int ypos; }; @@ -252,7 +289,7 @@ const int maxItems = 20; // a list is limited to this many things struct item TheList[maxItems]; // the list above is copied into here to allow modification -item * whichList; // pointer to current draw list +const item* whichList; // pointer to current draw list // Menu flag bits are now variables bool InMenu = false; // 1 if currently in a menu at all @@ -293,7 +330,7 @@ bool driver_active[CNT_DEVICES] = {false, false, false, false, false, false}; // ----------------------- DS3232 time keeping code ---------------------------------- // Make day of week from date variables -int GetWDay(int d, int m, int yr, int cent) +int GetWDay(int d, int m, int yr, int cent) { int weekday; int y = cent*100 + yr; @@ -303,8 +340,8 @@ int GetWDay(int d, int m, int yr, int cent) // Sets the RTC to the current time, called when exiting the time setting menu void writeRTCtime() -{ - int yr, mo, dy, dw, hr, mi, sc; +{ + int yr, mo, dy, dw, hr, mi, sc; // convert our decimal values to BCD sc = Secs%10 + ((Secs/10) << 4); // run enable: bit 7 = 0 @@ -329,9 +366,9 @@ void writeRTCtime() // Sets the RTC to the current locale, called when exiting the locale setting menu void writeRTClocale() -{ +{ int zn = Zone + 30; // make it fit in an unsigned byte so it won't get garbled - + Wire.beginTransmission(DS3232_ADDRESS); Wire.write(0x18); // register select is in the SRAM region of the DS3232 Wire.write(rtcMagic); // flag the RTC data as being valid @@ -347,7 +384,7 @@ void writeRTClocale() void readRTCtime() { // int yr, mo, dy, dw, hr, mi, sc; // not using day of week now... fix this!!! - int yr, mo, dy, hr, mi, sc; + int yr, mo, dy, hr, mi, sc; Wire.beginTransmission(DS3232_ADDRESS); Wire.write(00); // read data starting at byte 00 @@ -417,11 +454,11 @@ static void readGPStime(TinyGPS &gps) { byte mon, days, hr, mins, sec, hund; int yrs; - + gps.crack_datetime(&yrs, &mon, &days, &hr, &mins, &sec, &hund, &GPSage); - - GPSHun = hund; - GPSSec = sec; + + GPSHun = hund; + GPSSec = sec; GPSMin = mins; GPSHrs = hr; GPSDay = days; @@ -440,18 +477,18 @@ const int NDays[] = {0,31,28,31,30,31,30,31,31,30,31,30,31, // normal year // Move forwards in calendar if needed due to GPS -> local conversion // Figures out month lengths, century, etc. -void IncDays(void) +void IncDays(void) { int lastDay; if (Years % 4) lastDay = NDays[Mons + 12]; // a leap year else lastDay = NDays[Mons]; // not a leap year Days += 1; - if (Days > lastDay) + if (Days > lastDay) { Days = 1; // begin the next month Mons += 1; - if (Mons > 12) + if (Mons > 12) { Mons = 1; Years += 1; @@ -467,17 +504,17 @@ void IncDays(void) // Move backwards in calendar if needed due to GPS -> local conversion // On month borrow, we go to the last day in the previous month // Figures out month lengths, century, etc. -void DecDays(void) +void DecDays(void) { Days -= 1; - if (Days == 0) + if (Days == 0) { Mons -= 1; // goto last day of prev month - if (Mons == 0) + if (Mons == 0) { Mons = 12; Years -= 1; - if (Years < 0) + if (Years < 0) { Years = 99; Century -= 1; @@ -511,7 +548,7 @@ void getTheTime(void) // deal with the fact that GPS is UTC, but we display local time Hrs = GPSHrs + Zone + DST; // Hour from GPS receiver, shifted to local time Mins = GPSMin + (Zone > 0 ? ZMins : -ZMins); // Minute from GPS receiver - + // The minutes and hours may be out of range. Correct them if so if (Mins > 59) { @@ -521,7 +558,7 @@ void getTheTime(void) { Hrs--; } - if (Hrs > 23) + if (Hrs > 23) { Hrs -= 24; IncDays(); // do some math on the calendar @@ -567,7 +604,7 @@ int EncTab[] = {none,decr,none,impos, // 00 // Initialize the encoder history to match its position void InitEnc() { - LastEnc = digitalRead(encBPin) << 1 | digitalRead(encAPin); + LastEnc = digitalRead(encBPin) << 1 | digitalRead(encAPin); LastEnc = LastEnc * 5; // copy of old and new next to each other } @@ -575,7 +612,7 @@ void InitEnc() // This must be called exactly once per MainLp loop // Returns # of detents in EncDir, -=CCW, +=CW void DoEnc() { - LastEnc = LastEnc >> 2 | digitalRead(encBPin) << 3 | digitalRead(encAPin) << 2; + LastEnc = LastEnc >> 2 | digitalRead(encBPin) << 3 | digitalRead(encAPin) << 2; EncDir = EncDir + EncTab[LastEnc]; // bump encoder value by motion via lookup table } diff --git a/SCTVcode/b_font.ino b/SCTVcode/b_font.ino index 4d0eb69..28d46af 100644 --- a/SCTVcode/b_font.ino +++ b/SCTVcode/b_font.ino @@ -1,6 +1,6 @@ // -------------------- 12x20 proportional font ------------------ -// Table is in ASCII character order. +// Table is in ASCII character order. // An index table Font points to entries in this list // to allow variable segment count. @@ -38,247 +38,247 @@ const int OurChrHt = 20; // this font's character height // circle: cir,XC,YC,XS,YS,FO,LO{,width|0x80} // line: lin,XS,YS,XE,YE,FO,LO{,width|0x80} const int Space[] = {0x86}; // space does nothing but move over -const int Exclam[] = { lin, 1, 6, 1,20, 6,13, +const int Exclam[] = { lin, 1, 6, 1,20, 6,13, cir, 1, 1, 2, 2, 6,13, 0x82}; -const int DQuot[] = { lin, 0,12, 0,20, 6,13, +const int DQuot[] = { lin, 0,12, 0,20, 6,13, lin, 6,12, 6,20, 6,13, 0x86}; -const int Sharp[] = { lin, 2, 4, 4,20, 6,13, - lin, 7, 4, 9,20, 6,13, - lin, 0, 9,10, 9, 6,13, +const int Sharp[] = { lin, 2, 4, 4,20, 6,13, + lin, 7, 4, 9,20, 6,13, + lin, 0, 9,10, 9, 6,13, lin, 1,15,11,15, 6,13, 0x8c}; const int Dollar[] = { cir, 5, 6,10, 8, 4, 9, - cir, 5,14,10, 8, 0, 5, + cir, 5,14,10, 8, 0, 5, lin, 5, 2, 5,22, 6,13, 0x8a}; -const int Percent[] = { cir, 3,17, 6, 6, 6,13, - cir, 9, 3, 6, 6, 6,13, +const int Percent[] = { cir, 3,17, 6, 6, 6,13, + cir, 9, 3, 6, 6, 6,13, lin, 3, 0,15,20, 6,13, 0x8c}; const int Amper[] = { cir, 4,15, 8,10, 6,12, - cir, 4, 5, 8,10, 2, 5, - cir, 4, 8,16,16, 6, 7, + cir, 4, 5, 8,10, 2, 5, + cir, 4, 8,16,16, 6, 7, lin, 1,12,11, 0, 6,13, 0x8c}; -const int Apost[] = { cir, 3,19, 2, 2, 6,13, +const int Apost[] = { cir, 3,19, 2, 2, 6,13, cir, 0,19, 8,12, 6, 7, 0x84}; const int LParen[] = { cir, 4,10, 8,20, 2, 5, 0x84}; const int RParen[] = { cir, 0,10, 8,20, 6, 9, 0x84}; -const int Aster[] = { lin, 0,10,12,10, 6,13, - lin, 2, 4,10,16, 6,13, +const int Aster[] = { lin, 0,10,12,10, 6,13, + lin, 2, 4,10,16, 6,13, lin, 2,16,10, 4, 6,13, 0x8c}; -const int Plus[] = { lin, 0,10,12,10, 6,13, +const int Plus[] = { lin, 0,10,12,10, 6,13, lin, 6, 4, 6,16, 6,13, 0x8c}; -const int Comma[] = { cir, 3, 1, 2, 2, 6,13, +const int Comma[] = { cir, 3, 1, 2, 2, 6,13, cir, 0, 1, 8,12, 6, 7, 0x84}; const int Minus[] = { lin, 0,10,12,10, 6,13, 0x8c}; const int Period[] = { cir, 1, 1, 2, 2, 6,13, 0x82}; const int Slash[] = { lin, 0, 0,12,20, 6,13, 0x8c}; const int Zero[] = { cir, 6,10,12,20, 6,13, 0x8c}; -const int One[] = { lin, 7, 0, 7,20, 6,13, +const int One[] = { lin, 7, 0, 7,20, 6,13, lin, 3,16, 7,20, 6,13, 0x8c}; const int Two[] = { cir, 6,14,12,12, 6,11, - cir, 6, 0,12,16, 2, 3, + cir, 6, 0,12,16, 2, 3, lin, 0, 0,12, 0, 6,13, 0x8c}; const int Three[] = { cir, 6, 6,12,12, 5, 9, - lin, 1,20,11,20, 6,13, + lin, 1,20,11,20, 6,13, lin, 6,12,11,20, 6,13, 0x8c}; -const int Four[] = { lin, 8, 0, 8,20, 6,13, - lin, 0, 6,12, 6, 6,13, +const int Four[] = { lin, 8, 0, 8,20, 6,13, + lin, 0, 6,12, 6, 6,13, lin, 0, 6, 8,20, 6,13, 0x8c}; const int Five[] = { cir, 6, 6,12,12, 5,10, - lin, 2,10, 4,20, 6,13, + lin, 2,10, 4,20, 6,13, lin, 4,20,12,20, 6,13, 0x8c}; -const int Six[] = { cir, 6, 6,12,12, 6,13, +const int Six[] = { cir, 6, 6,12,12, 6,13, lin, 2,11, 8,20, 6,13, 0x8c}; -const int Seven[] = { lin, 0, 0,12,20, 6,13, +const int Seven[] = { lin, 0, 0,12,20, 6,13, lin, 0,20,12,20, 6,13, 0x8c}; -const int Eight[] = { cir, 6, 6,12,12, 6,13, +const int Eight[] = { cir, 6, 6,12,12, 6,13, cir, 6,16, 8, 8, 6,13, 0x8c}; -const int Nine[] = { cir, 6,14,12,12, 6,13, +const int Nine[] = { cir, 6,14,12,12, 6,13, lin, 4, 0,10, 9, 6,13, 0x8c}; -const int Colon[] = { cir, 2, 6, 4, 4, 6,13, +const int Colon[] = { cir, 2, 6, 4, 4, 6,13, cir, 2,14, 4, 4, 6,13, 0x84}; -const int SemiCol[] = { cir, 3,14, 2, 2, 6,13, - cir, 3, 6, 2, 2, 6,13, +const int SemiCol[] = { cir, 3,14, 2, 2, 6,13, + cir, 3, 6, 2, 2, 6,13, cir, 0, 6, 8,12, 6, 7, 0x84}; -const int LThan[] = { lin, 0,10,12,18, 6,13, +const int LThan[] = { lin, 0,10,12,18, 6,13, lin, 0,10,12, 2, 6,13, 0x8c}; -const int Equal[] = { lin, 0,13,12,13, 6,13, +const int Equal[] = { lin, 0,13,12,13, 6,13, lin, 0, 7,12, 7, 6,13, 0x8c}; -const int GThan[] = { lin, 0,18,12,10, 6,13, +const int GThan[] = { lin, 0,18,12,10, 6,13, lin, 0, 2,12,10, 6,13, 0x8c}; const int Quest[] = { cir, 5,14,10,10, 6,11, cir, 5, 7, 4, 4, 2, 7, cir, 5, 1, 2, 2, 6,13, 0x8a}; -const int AtSign[] = { cir, 3,10, 6,10, 6,13, +const int AtSign[] = { cir, 3,10, 6,10, 6,13, cir, 3,10,14,20, 0, 6, cir, 8,10, 4, 4, 4, 7, 0x8c}; -const int BigA[] = { lin, 0, 0, 6,20, 6,13, - lin, 6,20,12, 0, 6,13, +const int BigA[] = { lin, 0, 0, 6,20, 6,13, + lin, 6,20,12, 0, 6,13, lin, 3, 8, 9, 8, 6,13, 0x8c}; -const int BigB[] = { lin, 0, 0, 0,20, 6,13, - lin, 0, 0, 8, 0, 6,13, - lin, 0,10, 8,10, 6,13, - lin, 0,20, 8,20, 6,13, - cir, 8, 5,10,10, 6, 9, +const int BigB[] = { lin, 0, 0, 0,20, 6,13, + lin, 0, 0, 8, 0, 6,13, + lin, 0,10, 8,10, 6,13, + lin, 0,20, 8,20, 6,13, + cir, 8, 5,10,10, 6, 9, cir, 8,15,10,10, 6, 9, 0x8c}; const int BigC[] = { cir, 7,10,14,20, 1, 6, 0x8c}; -const int BigD[] = { lin, 0, 0, 0,20, 6,13, - lin, 0, 0, 4, 0, 6,13, - lin, 0,20, 4,20, 6,13, +const int BigD[] = { lin, 0, 0, 0,20, 6,13, + lin, 0, 0, 4, 0, 6,13, + lin, 0,20, 4,20, 6,13, cir, 4,10,16,20, 6, 9, 0x8c}; -const int BigE[] = { lin, 0, 0, 0,20, 6,13, - lin, 0, 0,12, 0, 6,13, - lin, 0,10, 8,10, 6,13, +const int BigE[] = { lin, 0, 0, 0,20, 6,13, + lin, 0, 0,12, 0, 6,13, + lin, 0,10, 8,10, 6,13, lin, 0,20,12,20, 6,13, 0x8c}; -const int BigF[] = { lin, 0, 0, 0,20, 6,13, - lin, 0,10, 8,10, 6,13, +const int BigF[] = { lin, 0, 0, 0,20, 6,13, + lin, 0,10, 8,10, 6,13, lin, 0,20,12,20, 6,13, 0x8c}; const int BigG[] = { cir, 7,10,14,20, 1, 6, - lin,11, 2,11, 8, 6,13, + lin,11, 2,11, 8, 6,13, lin, 7, 8,11, 8, 6,13, 0x8c}; -const int BigH[] = { lin, 0, 0, 0,20, 6,13, - lin,12, 0,12,20, 6,13, +const int BigH[] = { lin, 0, 0, 0,20, 6,13, + lin,12, 0,12,20, 6,13, lin, 0,10,12,10, 6,13, 0x8c}; -const int BigI[] = { lin, 2, 0, 2,20, 6,13, - lin, 1, 0, 5, 0, 6,13, +const int BigI[] = { lin, 2, 0, 2,20, 6,13, + lin, 1, 0, 5, 0, 6,13, lin, 1,20, 5,20, 6,13, 0x84}; -const int BigJ[] = { lin,12, 6,12,20, 6,13, +const int BigJ[] = { lin,12, 6,12,20, 6,13, cir, 6, 6,12,12, 4, 7, 0x8c}; -const int BigK[] = { lin, 0, 0, 0,20, 6,13, - lin, 0,10,12, 0, 6,13, +const int BigK[] = { lin, 0, 0, 0,20, 6,13, + lin, 0,10,12, 0, 6,13, lin, 0,10,12,20, 6,13, 0x8c}; -const int BigL[] = { lin, 0, 0, 0,20, 6,13, +const int BigL[] = { lin, 0, 0, 0,20, 6,13, lin, 0, 0,12, 0, 6,13, 0x8c}; -const int BigM[] = { lin, 0, 0, 0,20, 6,13, - lin,12, 0,12,20, 6,13, - lin, 0,20, 6,10, 6,13, +const int BigM[] = { lin, 0, 0, 0,20, 6,13, + lin,12, 0,12,20, 6,13, + lin, 0,20, 6,10, 6,13, lin, 6,10,12,20, 6,13, 0x8c}; -const int BigN[] = { lin, 0, 0, 0,20, 6,13, - lin,12, 0,12,20, 6,13, +const int BigN[] = { lin, 0, 0, 0,20, 6,13, + lin,12, 0,12,20, 6,13, lin, 0,20,12, 0, 6,13, 0x8c}; const int BigO[] = { cir, 6,10,12,20, 6,13, 0x8c}; -const int BigP[] = { lin, 0, 0, 0,20, 6,13, - lin, 0,10, 8,10, 6,13, - lin, 0,20, 8,20, 6,13, +const int BigP[] = { lin, 0, 0, 0,20, 6,13, + lin, 0,10, 8,10, 6,13, + lin, 0,20, 8,20, 6,13, cir, 8,15,10,10, 6, 9, 0x8c}; -const int BigQ[] = { cir, 6,10,12,20, 6,13, +const int BigQ[] = { cir, 6,10,12,20, 6,13, lin, 8, 6,12, 0, 6,13, 0x8c}; -const int BigR[] = { lin, 0, 0, 0,20, 6,13, - lin, 0,10, 8,10, 6,13, - lin, 0,20, 8,20, 6,13, - cir, 8,15,10,10, 6, 9, +const int BigR[] = { lin, 0, 0, 0,20, 6,13, + lin, 0,10, 8,10, 6,13, + lin, 0,20, 8,20, 6,13, + cir, 8,15,10,10, 6, 9, lin, 6,10,12, 0, 6,13, 0x8c}; const int BigS[] = { cir, 6, 5,12,10, 4, 9, cir, 6,15,12,10, 0, 5, 0x8c}; -const int BigT[] = { lin, 6, 0, 6,20, 6,13, +const int BigT[] = { lin, 6, 0, 6,20, 6,13, lin, 0,20,12,20, 6,13, 0x8c}; -const int BigU[] = { lin, 0, 6, 0,20, 6,13, - lin,12, 6,12,20, 6,13, +const int BigU[] = { lin, 0, 6, 0,20, 6,13, + lin,12, 6,12,20, 6,13, cir, 6, 6,12,12, 4, 7, 0x8c}; -const int BigV[] = { lin, 0,20, 6, 0, 6,13, +const int BigV[] = { lin, 0,20, 6, 0, 6,13, lin, 6, 0,12,20, 6,13, 0x8c}; -const int BigW[] = { lin, 0, 0, 0,20, 6,13, - lin,12, 0,12,20, 6,13, - lin, 0, 0, 6,10, 6,13, +const int BigW[] = { lin, 0, 0, 0,20, 6,13, + lin,12, 0,12,20, 6,13, + lin, 0, 0, 6,10, 6,13, lin, 6,10,12, 0, 6,13, 0x8c}; -const int BigX[] = { lin, 0,20,12, 0, 6,13, +const int BigX[] = { lin, 0,20,12, 0, 6,13, lin, 0, 0,12,20, 6,13, 0x8c}; -const int BigY[] = { lin, 6, 0, 6,10, 6,13, - lin, 0,20, 6,10, 6,13, +const int BigY[] = { lin, 6, 0, 6,10, 6,13, + lin, 0,20, 6,10, 6,13, lin, 6,10,12,20, 6,13, 0x8c}; -const int BigZ[] = { lin, 0, 0,12,20, 6,13, - lin, 0, 0,12, 0, 6,13, +const int BigZ[] = { lin, 0, 0,12,20, 6,13, + lin, 0, 0,12, 0, 6,13, lin, 0,20,12,20, 6,13, 0x8c}; -const int LftSqBr[] = { lin, 0, 0, 0,20, 6,13, - lin, 0, 0, 4, 0, 6,13, +const int LftSqBr[] = { lin, 0, 0, 0,20, 6,13, + lin, 0, 0, 4, 0, 6,13, lin, 0,20, 4,20, 6,13, 0x84}; const int BackSl[] = { lin, 0,20,12, 0, 6,13, 0x8c}; -const int RtSqBr[] = { lin, 4, 0, 4,20, 6,13, - lin, 0, 0, 4, 0, 6,13, +const int RtSqBr[] = { lin, 4, 0, 4,20, 6,13, + lin, 0, 0, 4, 0, 6,13, lin, 0,20, 4,20, 6,13, 0x84}; -const int Carat[] = { lin, 0,10, 6,16, 6,13, +const int Carat[] = { lin, 0,10, 6,16, 6,13, lin, 6,16,12,10, 6,13, 0x8c}; const int UnderSc[] = { lin, 0, 0,12, 0, 6,13, 0x8c}; const int BackQu[] = { lin, 0,20, 4,12, 6,13, 0x84}; -const int SmallA[] = { cir, 5, 6,10,12, 6,13, +const int SmallA[] = { cir, 5, 6,10,12, 6,13, lin,10, 0,10,12, 6,13, 0x8a}; -const int SmallB[] = { cir, 5, 6,10,12, 6,13, +const int SmallB[] = { cir, 5, 6,10,12, 6,13, lin, 0, 0, 0,20, 6,13, 0x8a}; const int SmallC[] = { cir, 5, 6,10,12, 1, 6, 0x88}; -const int SmallD[] = { cir, 5, 6,10,12, 6,13, +const int SmallD[] = { cir, 5, 6,10,12, 6,13, lin,10, 0,10,20, 6,13, 0x8a}; const int SmallE[] = { cir, 5, 6,10,12, 0, 6, lin, 0, 6,10, 6, 6,13, 0x8a}; -const int SmallF[] = { cir, 7,16, 6, 8, 0, 3, - lin, 0,10, 8,10, 6,13, +const int SmallF[] = { cir, 7,16, 6, 8, 0, 3, + lin, 0,10, 8,10, 6,13, lin, 4, 0, 4,16, 6,13, 0x8a}; -const int SmallG[] = { cir, 5, 6,10,12, 6,13, - lin,10, 0,10,12, 6,13, +const int SmallG[] = { cir, 5, 6,10,12, 6,13, + lin,10, 0,10,12, 6,13, cir, 5, 0,10,12, 5, 7, 0x8a}; -const int SmallH[] = { cir, 4, 8, 8, 8, 0, 3, - lin, 0, 0, 0,20, 6,13, +const int SmallH[] = { cir, 4, 8, 8, 8, 0, 3, + lin, 0, 0, 0,20, 6,13, lin, 8, 0, 8, 8, 6,13, 0x88}; -const int SmallI[] = { cir, 1,16, 2, 2, 6,13, +const int SmallI[] = { cir, 1,16, 2, 2, 6,13, lin, 1, 0, 1,12, 6,13, 0x82}; -const int SmallJ[] = { cir, 6,16, 2, 2, 6,13, - lin, 6, 0, 6,12, 6,13, +const int SmallJ[] = { cir, 6,16, 2, 2, 6,13, + lin, 6, 0, 6,12, 6,13, cir, 3, 0, 6, 8, 5, 7, 0x88}; -const int SmallK[] = { lin, 0, 0, 0,20, 6,13, - lin, 0, 4, 8,12, 6,13, +const int SmallK[] = { lin, 0, 0, 0,20, 6,13, + lin, 0, 4, 8,12, 6,13, lin, 1, 6, 7, 0, 6,13, 0x88}; const int SmallL[] = { lin, 1, 0, 1,20, 6,13, 0x82}; -const int SmallM[] = { lin, 0, 0, 0,12, 6,13, - cir, 4, 8, 8, 8, 0, 3, - lin, 8, 0, 8, 8, 6,13, - cir,12, 8, 8, 8, 0, 3, +const int SmallM[] = { lin, 0, 0, 0,12, 6,13, + cir, 4, 8, 8, 8, 0, 3, + lin, 8, 0, 8, 8, 6,13, + cir,12, 8, 8, 8, 0, 3, lin,16, 0,16, 8, 6,13, 0x90}; -const int SmallN[] = { lin, 0, 0, 0,12, 6,13, - cir, 4, 8, 8, 8, 0, 3, +const int SmallN[] = { lin, 0, 0, 0,12, 6,13, + cir, 4, 8, 8, 8, 0, 3, lin, 8, 0, 8, 8, 6,13, 0x88}; const int SmallO[] = { cir, 5, 6,10,12, 6,13, 0x8a}; -const int SmallP[] = { cir, 5, 6,10,12, 6,13, +const int SmallP[] = { cir, 5, 6,10,12, 6,13, lin, 0,-4, 0,12, 6,13, 0x8a}; -const int SmallQ[] = { cir, 5, 6,10,12, 6,13, +const int SmallQ[] = { cir, 5, 6,10,12, 6,13, lin,10,-4,10,12, 6,13, 0x8a}; -const int SmallR[] = { lin, 0, 0, 0,12, 6,13, +const int SmallR[] = { lin, 0, 0, 0,12, 6,13, cir, 5, 6,10,12, 1, 3, 0x88}; -const int SmallS[] = { cir, 4, 9, 8, 6, 0, 5, +const int SmallS[] = { cir, 4, 9, 8, 6, 0, 5, cir, 4, 3, 8, 6, 4, 9, 0x88}; -const int SmallT[] = { // cir, 8, 4, 8, 8, 4, 5, - lin, 0,12, 8,12, 6,13, +const int SmallT[] = { // cir, 8, 4, 8, 8, 4, 5, + lin, 0,12, 8,12, 6,13, lin, 4, 0, 4,16, 6,13, 0x88}; -const int SmallU[] = { lin, 8, 0, 8,12, 6,13, - cir, 4, 4, 8, 8, 4, 7, +const int SmallU[] = { lin, 8, 0, 8,12, 6,13, + cir, 4, 4, 8, 8, 4, 7, lin, 0, 4, 0,12, 6,13, 0x88}; -const int SmallV[] = { lin, 0,12, 4, 0, 6,13, +const int SmallV[] = { lin, 0,12, 4, 0, 6,13, lin, 4, 0, 8,12, 6,13, 0x88}; -const int SmallW[] = { lin, 0,12, 4, 0, 6,13, - lin, 4, 0, 8,12, 6,13, - lin, 8,12,12, 0, 6,13, +const int SmallW[] = { lin, 0,12, 4, 0, 6,13, + lin, 4, 0, 8,12, 6,13, + lin, 8,12,12, 0, 6,13, lin,12, 0,16,12, 6,13, 0x90}; -const int SmallX[] = { lin, 0,12, 8, 0, 6,13, +const int SmallX[] = { lin, 0,12, 8, 0, 6,13, lin, 0, 0, 8,12, 6,13, 0x88}; -const int SmallY[] = { lin, 0,12, 4, 0, 6,13, - lin, 4, 0, 8,12, 6,13, +const int SmallY[] = { lin, 0,12, 4, 0, 6,13, + lin, 4, 0, 8,12, 6,13, cir, 1, 0, 6, 8, 6, 7, 0x88}; -const int SmallZ[] = { lin, 0, 0, 8, 0, 6,13, - lin, 0,12, 8,12, 6,13, +const int SmallZ[] = { lin, 0, 0, 8, 0, 6,13, + lin, 0,12, 8,12, 6,13, lin, 0, 0, 8,12, 6,13, 0x88}; -const int LfBrace[] = { cir, 8, 6, 8,12, 4, 5, - cir, 0, 6, 8, 8, 0, 1, - cir, 0,14, 8, 8, 6, 7, +const int LfBrace[] = { cir, 8, 6, 8,12, 4, 5, + cir, 0, 6, 8, 8, 0, 1, + cir, 0,14, 8, 8, 6, 7, cir, 8,14, 8,12, 2, 3, 0x88}; const int VertBar[] = { lin, 1, 1, 1,21, 6,13, 0x82}; -const int RtBrace[] = { cir, 0, 6, 8,12, 6, 7, - cir, 8, 6, 8, 8, 2, 3, - cir, 8,14, 8, 8, 4, 5, +const int RtBrace[] = { cir, 0, 6, 8,12, 6, 7, + cir, 8, 6, 8, 8, 2, 3, + cir, 8,14, 8, 8, 4, 5, cir, 0,14, 8,12, 0, 1, 0x88}; -const int Tilde[] = { cir, 3,12, 6, 4, 0, 3, +const int Tilde[] = { cir, 3,12, 6, 4, 0, 3, cir, 9,12, 6, 4, 4, 7, 0x8c}; -const int Rubout[] = { lin, 0,10, 6,20, 6,13, - lin, 0, 0,12,20, 6,13, +const int Rubout[] = { lin, 0,10, 6,20, 6,13, + lin, 0, 0,12,20, 6,13, lin, 6, 0,12,10, 6,13, 0x8c}; // All the characters, arranged in ASCII order because ASCII rules -const int * const Font[] = +const int * const Font[] = {Space, Exclam,DQuot, Sharp, Dollar, Percent,Amper, Apost, LParen,RParen,Aster, Plus, Comma, Minus, Period,Slash, Zero, One, Two, Three, Four, Five, Six, Seven, diff --git a/SCTVcode/d_drawing.ino b/SCTVcode/d_drawing.ino index 68d49b6..40417e2 100644 --- a/SCTVcode/d_drawing.ino +++ b/SCTVcode/d_drawing.ino @@ -2,10 +2,10 @@ // SetScale sets the character size parameters from Scale // There are two char spacings - tight for big, looser for small scale -void SetScale() +void SetScale() { ChrHt = Scale * OurChrHt; - if (Scale < 40) + if (Scale < 40) { Kern = Scale * OurLilKern; RowGap = Scale * OurLilGap; @@ -22,16 +22,16 @@ void SetScale() // Entered with the display blanked. // Exits with the display blanked. -// Uses some math to draw each dot exactly once, with the number of dots calculated -// to produce a good even display brightness. The dots are close enough together that they -// are smeared together into a line or arc. -// +// Uses some math to draw each dot exactly once, with the number of dots calculated +// to produce a good even display brightness. The dots are close enough together that they +// are smeared together into a line or arc. +// // Scaling: -// The DACs are 12 bits, giving a field of 4096 square. We use 2500 for the active field, -// centered at (0,0). -// with the rest being extra room for the x and y position controls to work. +// The DACs are 12 bits, giving a field of 4096 square. We use 2500 for the active field, +// centered at (0,0). +// with the rest being extra room for the x and y position controls to work. // -void DoSeg() +void DoSeg() { int len, xmotion, ymotion, motion, xstart, ystart; // if (doingHand) Serial.printf("shape %d ", Shape); @@ -39,10 +39,10 @@ void DoSeg() // draw a circle int xcen = XCenter * Scale + ChrXPos + XSaver + xPos + midDAC; // X center position int ycen = YCenter * Scale + ChrYPos + YSaver + yPos + midDAC; // Y center position - int xrad = (XSize * Scale) / 2; // X size: radius is diameter/2 + int xrad = (XSize * Scale) / 2; // X size: radius is diameter/2 int yrad = (YSize * Scale) / 2; // Y size int firstAngle = FirstO * (nsteps >> 3); - int lastAngle = (LastO + 1) * (nsteps >> 3); + int lastAngle = (LastO + 1) * (nsteps >> 3); int bigness = (xrad > yrad ? xrad : yrad ); int stride = (circleSpeed<<8) / bigness; // stride is scaled by 256 to allow finer resolution of step size xstart = ((costab[firstAngle] * xrad)>>16) + xcen; @@ -61,7 +61,7 @@ void DoSeg() delayMicroseconds(glowDelay); // wait for glow to start // draw the circle with the beam on, sride is 24.8 bits to allow fine rate control - for (i=(firstAngle<<8); i<(lastAngle<<8); i+=stride) { + for (int i = (firstAngle<<8); i < (lastAngle<<8); i += stride) { thisX = ((costab[(i>>8) % nsteps] * xrad) >> 16) + xcen; thisY = ((sintab[(i>>8) % nsteps] * yrad) >> 16) + ycen; analogWrite(XDACPin, thisX); @@ -71,16 +71,16 @@ void DoSeg() digitalWrite(BlankPin, LOW); // done, hide dot now } if (Shape == lin) { - // draw a line + // draw a line xstart = XStart * Scale + ChrXPos + XSaver + xPos + midDAC; // X start position ystart = YStart * Scale + ChrYPos + YSaver + yPos + midDAC; // Y start position int xlen = ((XEnd - XStart) * Scale); // X size int ylen = ((YEnd - YStart) * Scale); // Y size - if (xlen == 0) + if (xlen == 0) { len = abs(ylen); //save ourselves a square root and two muls when not needed } - else + else { if (ylen == 0) { @@ -88,10 +88,10 @@ void DoSeg() } else { - len = (int)sqrt(xlen * xlen + ylen * ylen); + len = static_cast(sqrt(xlen * xlen + ylen * ylen)); } } - if (len <= 0) len = lineStride; + if (len <= 0) len = lineStride; int xinc = ((xlen<<8)/len); int yinc = ((ylen<<8)/len); xmotion = abs(thisX - xstart); @@ -100,13 +100,13 @@ void DoSeg() // if (doingHand) Serial.printf("motion %4d len %4d\n", motion, len); analogWrite(XDACPin, xstart); analogWrite(YDACPin, ystart); - + delayMicroseconds(motion/motionDelay + settlingDelay); digitalWrite(BlankPin, HIGH); // start making photons delayMicroseconds(glowDelay); // wait for glow to start - + // if (doingHand) Serial.printf("len %4d stride %4d\n", len, lineStride); - for (i=0; i<(len); i += lineStride) { + for (int i = 0; i < len; i += lineStride) { thisX = ((i*xinc)>>(8)) + xstart; thisY = ((i*yinc)>>(8)) + ystart; analogWrite(XDACPin, thisX); @@ -153,7 +153,7 @@ void drawACircle(int xcenter, int ycenter, int diameter) { // // If the line is terminated with an NL, it sets NewL in MenuFlg and // subtracts one kern from the total width. -void GetWid() +void GetWid() { ChrCnt = 0; StrWid = 0; @@ -179,12 +179,12 @@ void GetWid() StrWid += Kern * ChrCnt; // no newline, retain kern after last char } } - -// Center centers a draw list, calculating X and Y string positions and storing them + +// Center centers a draw list, calculating X and Y string positions and storing them // in the copy of the drawlist. -// This is tricky, as a line of text is composed of multiple strings. Only the -// last string in each line has a newline char. +// This is tricky, as a line of text is composed of multiple strings. Only the +// last string in each line has a newline char. // We need the total line width for all strings in a line so that we may // calculate the start X position for each string. So we need this info @@ -202,11 +202,11 @@ void GetWid() // CentXLp sets the X positions and calculates the total height. // CentYLp sets the Y positions using the height. -// It returns without doing anything if there is a string that has a non-zero position. -// This is true in a drawlist such as pong or face clock. +// It returns without doing anything if there is a string that has a non-zero position. +// This is true in a drawlist such as pong or face clock. // center a draw list, filling in xpos and ypos fields for each element -void Center(struct item *list) +void Center(struct item *list) { int LinWid = 0; // scaled width of line in pixels int LinWids[10]; // array of line widths per line @@ -218,7 +218,7 @@ void Center(struct item *list) DispHt = 0; wp = LinWids; // array of widths of every line // CXLoop scans all lines of text, calcs height and widths - while (p->type != listend) + while (p->type != ItemType::listend) { if (p->xpos != 0) { @@ -240,12 +240,12 @@ void Center(struct item *list) } // calculate the Y start point from total size and row heights ChrYPos = ((DispHt - RowGap)/2); - + // this last loop fills in xpos and ypos in each string, based on entire drawlist NewL = true; wp = LinWids; p = list; - while (p->type != listend) + while (p->type != ItemType::listend) { Scale = p->scale; StrPtr = p->string; // read string pointer @@ -257,7 +257,7 @@ void Center(struct item *list) ChrYPos -= ChrHt; } NewL = false; - if (TheChr == '\n') + if (TheChr == '\n') NewL = true; p->xpos = ChrXPos; // write the real position into list ChrXPos += StrWid; @@ -269,22 +269,22 @@ void Center(struct item *list) } -// copy a draw list to TheList, since TheList is modified by Center(). -void copyList(struct item *list) +// copy a draw list to TheList, since TheList is modified by Center(). +void copyList(const item* list) { - item *p = list; - item *q = TheList; + const item* p = list; + item* q = TheList; p = list; - while (p->type != listend) + while (p->type != ItemType::listend) { q->type = p->type; q->scale = p->scale; q->func = p->func; - q->string = p->string; - q->xpos = p->xpos; - q->ypos = p->ypos; + q->string = p->string; + q->xpos = p->xpos; + q->ypos = p->ypos; p++; // look at next list element - q++; + q++; } q->type = p->type; // copy the last listend to terminate the list } @@ -311,17 +311,17 @@ int GetSeg() { } // DispStr displays the zero-terminated text string pointed to by StrPtr -void DispStr() +void DispStr() { int notLast; TheChr = (*StrPtr++); while ((TheChr >= 32)) // printable { - // look up character in ROM font table. This is tricky. + // look up character in ROM font table. This is tricky. TheSeg = Font[(TheChr & 0x7f) - 32]; notLast = GetSeg(); - while (notLast) + while (notLast) { DoSeg(); // display segments until last one found notLast = GetSeg(); @@ -334,22 +334,22 @@ void DispStr() // Display a draw list once -void DoAList(struct item *list) +void DoAList(struct item *list) { item *p = list; int TheItem = 0; // menu item currently being processed - char *DupPtr; // duplicate StrPtr for bright work + const char* DupPtr; // duplicate StrPtr for bright work int DupXPos; // copy for highlighted strings InField = false; - while (p->type != listend) + while (p->type != ItemType::listend) { Scale = p->scale; StrPtr = p->string; // read string pointer ChrXPos = p->xpos; // read position of string (not used by most!) ChrYPos = p->ypos; - // seg tells it to draw a circle or a line. This code does a circle. Need to do a line also. - if (p->type == seg) { + // seg tells it to draw a circle or a line. This code does a circle. Need to do a line also. + if (p->type == ItemType::seg) { XCenter = YCenter = 0; // position done by ChrX,YPos XSize = StrPtr[0]; // read out segment parameters from 'string' array YSize = StrPtr[1]; @@ -364,7 +364,7 @@ void DoAList(struct item *list) } else { - if (p->type != text) + if (p->type != ItemType::text) { // it's a menu item, so save its code pointer and count up items TheItem++; } @@ -372,13 +372,13 @@ void DoAList(struct item *list) DupXPos = ChrXPos; SetScale(); DispStr(); - if ((p->type != text) && (TheItem == HotItem)) + if ((p->type != ItemType::text) && (TheItem == HotItem)) { // hot, either highlight or blink item MenuCod = p->func; - if (p->type == field) + if (p->type == ItemType::field) { InField = true; - if (!InParam || Blink) + if (!InParam || Blink) { // if it's a parameter, blink it StrPtr = DupPtr; ChrXPos = DupXPos; @@ -400,7 +400,7 @@ void DoAList(struct item *list) } p++; } - NItems = TheItem; // will this work to set number of items? + NItems = TheItem; // will this work to set number of items? } // Once an hour, advance the screensaver to the next position @@ -408,7 +408,7 @@ void DoAList(struct item *list) // any phosphor burn over a 4 by 8 pixel area. // -// Screensaver moves the display impercetibly in a triangle raster scan +// Screensaver moves the display impercetibly in a triangle raster scan // every hour, to spread out the screen burn. const int nSavers = 31; int lastHour = 0; diff --git a/SCTVcode/g_clocks.ino b/SCTVcode/g_clocks.ino index bc3ba37..942379e 100644 --- a/SCTVcode/g_clocks.ino +++ b/SCTVcode/g_clocks.ino @@ -1,298 +1,282 @@ -// --------- Clock code --------------------------- - -// name the months of the year -const char janStr[] = "Jan"; -const char febStr[] = "Feb"; -const char marStr[] = "March"; -const char aprStr[] = "April"; -const char mayStr[] = "May"; -const char junStr[] = "June"; -const char julStr[] = "July"; -const char augStr[] = "Aug"; -const char sepStr[] = "Sept"; -const char octStr[] = "Oct"; -const char novStr[] = "Nov"; -const char decStr[] = "Dec"; - -const char* const JanStr[] = {janStr, febStr, marStr, aprStr, mayStr, junStr, - julStr, augStr, sepStr, octStr, novStr, decStr}; - -// Weekday strings -const char sunStr[] = "Sunday\n"; -const char monStr[] = "Monday\n"; -const char tueStr[] = "Tuesday\n"; -const char wedStr[] = "Wednesday\n"; -const char thuStr[] = "Thursday\n"; -const char friStr[] = "Friday\n"; -const char satStr[] = "Saturday\n"; - -const char* const SunStr[] = {sunStr, monStr, tueStr, wedStr, thuStr, friStr, satStr}; - -// Other time related strings -char WDayStr[16]; // weekday string with NL -char MonthStr[12]; // month abbreviation with built-in NL -char HrSelStr[8]; // 12 or 24 for time format - -// Time zone strings allow selection of +/-hh:mm in 15 min increments -char ZoneStr[] = "-07"; -char ZMinStr[] = "00"; -char DSTStr[] = "Off\n"; -char HzStr[] = "00"; - -// Time strings - These are updated by makeTimeStrings() -char CenStr[] = "00"; -char YrsStr[] = "00"; -char MonStr[] = "00"; -char DayStr[] = "00\n"; -char HrsStr[] = "00"; -char MinStr[] = "00"; -char SecStr[] = "00\n"; - -// Some fixed strings -char BlankLn[] = "\n"; -char ColStr[] = ":"; -char DashStr[] = "-"; -char SlaStr[] = "/"; -char SpaStr[] = " "; -char DoneStr[] = "Exit menu\n"; // done with this menu -char OnStr[] = "On \n"; // for on/off options like DST -char OffStr[] = "Off\n"; // both are 5 bytes for easy copying - -// The splash screen draw list -char scopeClock[] = "The Scope Clock\n"; -char fromStr[] = "from\n"; -char cathCorn[] = "Cathode Corner\n"; -char copyR[] = "(C)2021 David Forbes\n"; -struct item splashList[] = { - {text,12,0,scopeClock,0,0}, - {text,8,0,fromStr, 0,0}, - {text,12,0,cathCorn, 0,0}, - {text,10,0,BlankLn, 0,0}, - {text,6,0,versionNo, 0,0}, - {text,6,0,copyR, 0,0}, - {listend,0,0,BlankLn,0,0} -}; - -// ----------------------------- Analog clock drawing ------------------- - -// The Face draw list has circles for minor marks and Roman -// numerals for the compass points. A circle in the center too. -// The hands are drawn by DrawClk -// The positions of the numerals are trial-and-error. - -char romanI[] = "I"; -char romanII[] = "II"; -char romanIII[] = "III"; -char romanIIII[] = "IIII"; -char romanV[] = "V"; -char romanVI[] = "VI"; -char romanVII[] = "VII"; -char romanVIII[] = "VIII"; -char romanIX[] = "IX"; -char romanX[] = "X"; -char romanXI[] = "XI"; -char romanXII[] = "XII"; -struct item faceList[] = { - {text,10,0,romanI, 490, 760}, // 1 o'clock - {text,10,0,romanII, 820, 400}, // 2 o'clock - {text,10,0,romanIII, 900, -100}, // 3 o'clock - {text,10,0,romanIIII, 740, -590}, // 4 o'clock - {text,10,0,romanV, 400, -960}, // 5 o'clock - {text,10,0,romanVI, -100,-1080}, // 6 o'clock - {text,10,0,romanVII, -600, -960}, // 7 o'clock - {text,10,0,romanVIII, -1000, -600}, // 7 o'clock - {text,10,0,romanIX, -1040, -100}, // 9 o'clock - {text,10,0,romanX, -940, 400}, // 10 o'clock - {text,10,0,romanXI, -600, 760}, // 11 o'clock - {text,10,0,romanXII, -160, 880}, // 12 o'clock - {listend,0,0,BlankLn,0,0} -}; - -// Draw clock hand on screen - -// angle is the angle (0=N, 60=E, 120=S, 180=W) -// len is length of hand -void DoHand(int len, int angle) { - int handAngle = (angle*nsteps/240) % nsteps; // get angle in range of new sin/cos tab - YSize = costab[handAngle]/500; // swap X and Y, because 0 deg is at north CW like a clock, not east CCW like math - XSize = sintab[handAngle]/500; - XStart = XSize * 10 / 13; // start at center circle radius - YStart = YSize * 10 / 13; - XEnd = (len * XSize) >>8; // scale to hand length - YEnd = (len * YSize) >>8; - // Serial.printf("size %5d %5d start %5d %5d end %5d %5d\n", XSize, YSize, XStart, YStart, XEnd, YEnd); - Scale = 1; - ChrXPos = ChrYPos = 0; - Shape = lin; - DoSeg(); -} - -// DrawClk draws the three clock hands. They are drawn in fine -// increments of 1.5 degrees per step. The steps are calculated -// incorporating the smaller time units for smoother movement. -// The angle is (0=N, 60=E, 120=S, 180=W) -void DrawClk() { - drawACircle(0, 0, 180); // -// DoHand(250, (Ticks / HalfSec) << 1 + (Secs << 2)); // no Ticks right now, so no smooth sweep. - // doingHand = true; - DoHand(2500, Secs << 2); - DoHand(2000, (Secs / 15) + (Mins << 2)); - DoHand(1500, (Hrs % 12) * 20 + Mins / 3); - DoHand(2000, (Secs / 15) + (Mins << 2)); // make the hour and minute hands bright by doubling up - DoHand(1500, (Hrs % 12) * 20 + Mins / 3); - // doingHand = false; -} - -// ------------------------ digital clocks ----------------------------------- - -// total time/date/day digital clock draw list -struct item timefList[] = { - {text,20,0,WDayStr, 0,0}, // day of week - {text,20,0,HrsStr, 0,0}, // hours - {text,20,0,ColStr, 0,0}, // colon - {text,20,0,MinStr, 0,0}, // mins - {text,20,0,ColStr, 0,0}, // colon - {text,20,0,SecStr, 0,0}, // secs - {text,20,0,MonthStr,0,0}, // month - {text,20,0,SpaStr, 0,0}, - {text,20,0,DayStr, 0,0}, // day - {text,20,0,CenStr, 0,0}, // the full year - {text,20,0,YrsStr, 0,0}, - {text,20,0,BlankLn, 0,0}, - {listend,0,0,BlankLn, 0,0} -}; - -// 6 digit digital clock with date draw list -struct item time6dList[] = { - {text,16,0,MonthStr,0,0}, // months - {text,16,0,SpaStr, 0,0}, // space - {text,16,0,DayStr, 0,0}, // days - {text,40,0,HrsStr, 0,0}, // hours - {text,40,0,ColStr, 0,0}, // colon - {text,40,0,MinStr, 0,0}, // mins - {text,40,0,BlankLn, 0,0}, // next line - {text,30,0,SecStr, 0,0}, // secs - {listend,0,0,BlankLn, 0,0} -}; - - -// 4 digit digital clock with date draw list -struct item time4dList[] = { - {text,16,0,WDayStr, 0,0}, // weekday - {text,40,0,HrsStr, 0,0}, // hours - {text,40,0,ColStr, 0,0}, // colon - {text,40,0,MinStr, 0,0}, // mins - {text,40,0,BlankLn, 0,0}, // next line - {text,16,0,MonthStr,0,0}, // months - {text,16,0,SpaStr, 0,0}, // space - {text,16,0,DayStr, 0,0}, // days - {listend,0,0,BlankLn,0,0} -}; - - -// 6 digit digital clock draw list -struct item time6nList[] = { - {text,10,0,BlankLn, 0,0}, // make hh:mm line lower for better centered appearance - {text,40,0,HrsStr, 0,0}, // hours - {text,40,0,ColStr, 0,0}, // colon - {text,40,0,MinStr, 0,0}, // mins - {text,40,0,BlankLn, 0,0}, // next line - {text,30,0,SecStr, 0,0}, // secs - {listend,0,0,BlankLn,0,0} -}; - - -// 4 digit digital clock draw list -struct item time4nList[] = { - {text,40,0,HrsStr, 0,0}, // hours - {text,40,0,ColStr, 0,0}, // colon - {text,40,0,MinStr, 0,0}, // mins - {text,40,0,BlankLn, 0,0}, // next line - {listend,0,0,BlankLn,0,0} -}; - -// ----------------------- Time string generator ----------------------- - -// makeTimeStrings fills in the time and date strings in RAM with the -// current time in ASCII. The month and weekday strings are set also. -void makeTimeStrings() { - int hours, zon; // temp storage for manipulation - if (Hr12) - { - HrSelStr[0] = '1'; - HrSelStr[1] = '2'; - } - else - { - HrSelStr[0] = '2'; - HrSelStr[1] = '4'; - } - CenStr[0] = (Century / 10) | '0'; - CenStr[1] = (Century % 10) | '0'; - YrsStr[0] = (Years / 10) | '0'; - YrsStr[1] = (Years % 10) | '0'; - MonStr[0] = (Mons / 10) | '0'; - MonStr[1] = (Mons % 10) | '0'; - - DayStr[0] = (Days / 10) | '0'; - DayStr[1] = (Days % 10) | '0'; - DayStr[2] = '\n'; - - // make the day of month be one digit if leading zero - if (DayStr[0] == '0') - { - DayStr[0] = DayStr[1]; - DayStr[1] = '\n'; - DayStr[2] = 0; - } - - // read the weekday string from ROM - strcpy(WDayStr, SunStr[WDay]); - - // read the month string from ROM - strcpy(MonthStr, JanStr[Mons - 1]); - - hours = Hrs; // temp for doing 12 hour madness - if (Hr12) - { - if (hours == 0) hours = 12; - if (hours > 12) hours -= 12; - } - HrsStr[0] = (hours / 10) | '0'; - HrsStr[1] = (hours % 10) | '0'; - if ((Hr12) && (HrsStr[0] == '0')) - { - HrsStr[0] = HrsStr[1]; - HrsStr[1] = 0; // one digit if < 10 - } - MinStr[0] = (Mins / 10) | '0'; - MinStr[1] = (Mins % 10) | '0'; - SecStr[0] = (Secs / 10) | '0'; - SecStr[1] = (Secs % 10) | '0'; - HzStr[0] = (Hertz / 10) | '0'; - if (DST) - { - DSTStr[1] = 'n'; // DST on - DSTStr[2] = ' '; - } - else - { - DSTStr[1] = 'f'; - DSTStr[2] = 'f'; - } - zon = Zone; // temp copy of timezone to monge - if (zon >= 0) ZoneStr[0] = '+'; - else { - ZoneStr[0] = '-'; - zon = 0 - zon; // make it positive for display - } - ZoneStr[1] = (zon / 10) | '0'; - ZoneStr[2] = (zon % 10) | '0'; - if (ZoneStr[0] == '0') - { - ZoneStr[0] = ZoneStr[1]; - ZoneStr[1] = '\n'; // one digit if < 10 - } - ZMinStr[0] = (ZMins / 10) | '0'; - ZMinStr[1] = (ZMins % 10) | '0'; -} +// --------- Clock code --------------------------- + +#include + +constexpr std::array monthStrings { + "Jan", "Feb", "March", "April", "May", "June", + "July", "Aug", "Sept", "Oct", "Nov", "Dec", +}; + +// Weekday strings +const char sunStr[] = "Sunday\n"; +const char monStr[] = "Monday\n"; +const char tueStr[] = "Tuesday\n"; +const char wedStr[] = "Wednesday\n"; +const char thuStr[] = "Thursday\n"; +const char friStr[] = "Friday\n"; +const char satStr[] = "Saturday\n"; + +const char* const SunStr[] = {sunStr, monStr, tueStr, wedStr, thuStr, friStr, satStr}; + +// Other time related strings +char WDayStr[16]; // weekday string with NL +char MonthStr[12]; // month abbreviation with built-in NL +char HrSelStr[8]; // 12 or 24 for time format + +// Time zone strings allow selection of +/-hh:mm in 15 min increments +char ZoneStr[] = "-07"; +char ZMinStr[] = "00"; +char DSTStr[] = "Off\n"; +char HzStr[] = "00"; + +// Time strings - These are updated by makeTimeStrings() +char CenStr[] = "00"; +char YrsStr[] = "00"; +char MonStr[] = "00"; +char DayStr[] = "00\n"; +char HrsStr[] = "00"; +char MinStr[] = "00"; +char SecStr[] = "00\n"; + +// Some fixed strings +char BlankLn[] = "\n"; +char ColStr[] = ":"; +char DashStr[] = "-"; +char SlaStr[] = "/"; +char SpaStr[] = " "; +char DoneStr[] = "Exit menu\n"; // done with this menu +char OnStr[] = "On \n"; // for on/off options like DST +char OffStr[] = "Off\n"; // both are 5 bytes for easy copying + +// The splash screen draw list +const char scopeClock[] = "The Scope Clock\n"; +const char fromStr[] = "from\n"; +const char cathCorn[] = "Cathode Corner\n"; +const char copyR[] = "(C)2021 David Forbes\n"; +const char customized[] = "customized by Nikolas Klauser\n"; +constexpr struct item splashList[] = { + {ItemType::text,12,0,scopeClock,0,0}, + {ItemType::text,8,0,fromStr, 0,0}, + {ItemType::text,12,0,cathCorn, 0,0}, + {ItemType::text,10,0,BlankLn, 0,0}, + {ItemType::text,6,0,versionNo, 0,0}, + {ItemType::text,6,0,copyR, 0,0}, + {ItemType::text,6,0,customized, 0,0}, + {ItemType::listend,0,0,BlankLn,0,0} +}; + +// ----------------------------- Analog clock drawing ------------------- + +// The Face draw list has circles for minor marks and Roman +// numerals for the compass points. A circle in the center too. +// The hands are drawn by DrawClk +// The positions of the numerals are trial-and-error. + +constexpr std::array romanNums = { + "I", "II", "III", "IIII", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", +}; + +constexpr struct item faceList[] = { + {ItemType::text,10,0,romanNums[0], 490, 760}, // 1 o'clock + {ItemType::text,10,0,romanNums[1], 820, 400}, // 2 o'clock + {ItemType::text,10,0,romanNums[2], 900, -100}, // 3 o'clock + {ItemType::text,10,0,romanNums[3], 740, -590}, // 4 o'clock + {ItemType::text,10,0,romanNums[4], 400, -960}, // 5 o'clock + {ItemType::text,10,0,romanNums[5], -100,-1080}, // 6 o'clock + {ItemType::text,10,0,romanNums[6], -600, -960}, // 7 o'clock + {ItemType::text,10,0,romanNums[7], -1000, -600}, // 7 o'clock + {ItemType::text,10,0,romanNums[8], -1040, -100}, // 9 o'clock + {ItemType::text,10,0,romanNums[9], -940, 400}, // 10 o'clock + {ItemType::text,10,0,romanNums[10], -600, 760}, // 11 o'clock + {ItemType::text,10,0,romanNums[11], -160, 880}, // 12 o'clock + {ItemType::listend,0,0,BlankLn,0,0} +}; + +// Draw clock hand on screen + +// angle is the angle (0=N, 60=E, 120=S, 180=W) +// len is length of hand +void DoHand(int len, int angle) { + int handAngle = (angle*nsteps/240) % nsteps; // get angle in range of new sin/cos tab + YSize = costab[handAngle]/500; // swap X and Y, because 0 deg is at north CW like a clock, not east CCW like math + XSize = sintab[handAngle]/500; + XStart = XSize * 10 / 13; // start at center circle radius + YStart = YSize * 10 / 13; + XEnd = (len * XSize) >>8; // scale to hand length + YEnd = (len * YSize) >>8; + // Serial.printf("size %5d %5d start %5d %5d end %5d %5d\n", XSize, YSize, XStart, YStart, XEnd, YEnd); + Scale = 1; + ChrXPos = ChrYPos = 0; + Shape = lin; + DoSeg(); +} + +// DrawClk draws the three clock hands. They are drawn in fine +// increments of 1.5 degrees per step. The steps are calculated +// incorporating the smaller time units for smoother movement. +// The angle is (0=N, 60=E, 120=S, 180=W) +void DrawClk() { + drawACircle(0, 0, 180); // +// DoHand(250, (Ticks / HalfSec) << 1 + (Secs << 2)); // no Ticks right now, so no smooth sweep. + // doingHand = true; + DoHand(2500, Secs << 2); + DoHand(2000, (Secs / 15) + (Mins << 2)); + DoHand(1500, (Hrs % 12) * 20 + Mins / 3); + DoHand(2000, (Secs / 15) + (Mins << 2)); // make the hour and minute hands bright by doubling up + DoHand(1500, (Hrs % 12) * 20 + Mins / 3); + // doingHand = false; +} + +// ------------------------ digital clocks ----------------------------------- +/* +// total time/date/day digital clock draw list +struct item timefList[] = { + {text,20,0,WDayStr, 0,0}, // day of week + {text,20,0,HrsStr, 0,0}, // hours + {text,20,0,ColStr, 0,0}, // colon + {text,20,0,MinStr, 0,0}, // mins + {text,20,0,ColStr, 0,0}, // colon + {text,20,0,SecStr, 0,0}, // secs + {text,20,0,MonthStr,0,0}, // month + {text,20,0,SpaStr, 0,0}, + {text,20,0,DayStr, 0,0}, // day + {text,20,0,CenStr, 0,0}, // the full year + {text,20,0,YrsStr, 0,0}, + {text,20,0,BlankLn, 0,0}, + {listend,0,0,BlankLn, 0,0} +}; +*/ +// 6 digit digital clock with date draw list +constexpr struct item time6dList[] = { + {ItemType::text,16,0,MonthStr,0,0}, // months + {ItemType::text,16,0,SpaStr, 0,0}, // space + {ItemType::text,16,0,DayStr, 0,0}, // days + {ItemType::text,40,0,HrsStr, 0,0}, // hours + {ItemType::text,40,0,ColStr, 0,0}, // colon + {ItemType::text,40,0,MinStr, 0,0}, // mins + {ItemType::text,40,0,BlankLn, 0,0}, // next line + {ItemType::text,30,0,SecStr, 0,0}, // secs + {ItemType::listend,0,0,BlankLn, 0,0} +}; + + +// 4 digit digital clock with date draw list +constexpr struct item time4dList[] = { + {ItemType::text,16,0,WDayStr, 0,0}, // weekday + {ItemType::text,40,0,HrsStr, 0,0}, // hours + {ItemType::text,40,0,ColStr, 0,0}, // colon + {ItemType::text,40,0,MinStr, 0,0}, // mins + {ItemType::text,40,0,BlankLn, 0,0}, // next line + {ItemType::text,16,0,MonthStr,0,0}, // months + {ItemType::text,16,0,SpaStr, 0,0}, // space + {ItemType::text,16,0,DayStr, 0,0}, // days + {ItemType::listend,0,0,BlankLn,0,0} +}; + + +// 6 digit digital clock draw list +constexpr struct item time6nList[] = { + {ItemType::text,10,0,BlankLn, 0,0}, // make hh:mm line lower for better centered appearance + {ItemType::text,40,0,HrsStr, 0,0}, // hours + {ItemType::text,40,0,ColStr, 0,0}, // colon + {ItemType::text,40,0,MinStr, 0,0}, // mins + {ItemType::text,40,0,BlankLn, 0,0}, // next line + {ItemType::text,30,0,SecStr, 0,0}, // secs + {ItemType::listend,0,0,BlankLn,0,0} +}; + + +// 4 digit digital clock draw list +constexpr struct item time4nList[] = { + {ItemType::text,40,0,HrsStr, 0,0}, // hours + {ItemType::text,40,0,ColStr, 0,0}, // colon + {ItemType::text,40,0,MinStr, 0,0}, // mins + {ItemType::text,40,0,BlankLn, 0,0}, // next line + {ItemType::listend,0,0,BlankLn,0,0} +}; + +// ----------------------- Time string generator ----------------------- + +// makeTimeStrings fills in the time and date strings in RAM with the +// current time in ASCII. The month and weekday strings are set also. +void makeTimeStrings() { + int hours, zon; // temp storage for manipulation + if (Hr12) + { + HrSelStr[0] = '1'; + HrSelStr[1] = '2'; + } + else + { + HrSelStr[0] = '2'; + HrSelStr[1] = '4'; + } + CenStr[0] = (Century / 10) | '0'; + CenStr[1] = (Century % 10) | '0'; + YrsStr[0] = (Years / 10) | '0'; + YrsStr[1] = (Years % 10) | '0'; + MonStr[0] = (Mons / 10) | '0'; + MonStr[1] = (Mons % 10) | '0'; + + DayStr[0] = (Days / 10) | '0'; + DayStr[1] = (Days % 10) | '0'; + DayStr[2] = '\n'; + + // make the day of month be one digit if leading zero + if (DayStr[0] == '0') + { + DayStr[0] = DayStr[1]; + DayStr[1] = '\n'; + DayStr[2] = 0; + } + + // read the weekday string from ROM + strcpy(WDayStr, SunStr[WDay]); + + // read the month string from ROM + strcpy(MonthStr, monthStrings[Mons - 1]); + + hours = Hrs; // temp for doing 12 hour madness + if (Hr12) + { + if (hours == 0) hours = 12; + if (hours > 12) hours -= 12; + } + HrsStr[0] = (hours / 10) | '0'; + HrsStr[1] = (hours % 10) | '0'; + if ((Hr12) && (HrsStr[0] == '0')) + { + HrsStr[0] = HrsStr[1]; + HrsStr[1] = 0; // one digit if < 10 + } + MinStr[0] = (Mins / 10) | '0'; + MinStr[1] = (Mins % 10) | '0'; + SecStr[0] = (Secs / 10) | '0'; + SecStr[1] = (Secs % 10) | '0'; + HzStr[0] = (Hertz / 10) | '0'; + if (DST) + { + DSTStr[1] = 'n'; // DST on + DSTStr[2] = ' '; + } + else + { + DSTStr[1] = 'f'; + DSTStr[2] = 'f'; + } + zon = Zone; // temp copy of timezone to monge + if (zon >= 0) ZoneStr[0] = '+'; + else { + ZoneStr[0] = '-'; + zon = 0 - zon; // make it positive for display + } + ZoneStr[1] = (zon / 10) | '0'; + ZoneStr[2] = (zon % 10) | '0'; + if (ZoneStr[0] == '0') + { + ZoneStr[0] = ZoneStr[1]; + ZoneStr[1] = '\n'; // one digit if < 10 + } + ZMinStr[0] = (ZMins / 10) | '0'; + ZMinStr[1] = (ZMins % 10) | '0'; +} diff --git a/SCTVcode/m_haiku.ino b/SCTVcode/m_haiku.ino index 8ca6d39..e51cb0f 100644 --- a/SCTVcode/m_haiku.ino +++ b/SCTVcode/m_haiku.ino @@ -1,6 +1,6 @@ // ---------------------- haiku drawing ------------------------------- -const char haikus[][4][50] = { +const char haikus[][4][50] = { {"I can only write\n","These haikus by using my\n","Fingers to help count\n","Sally Hunter\n"}, {"I adore all cats\n","I want to pet, scritch, boop, kiss!\n","But they want to bite\n","Sally Hunter\n"}, {"The candy store of\n","My heart sells only gumballs\n","When you are not here\n","Sally Hunter\n"}, @@ -316,12 +316,12 @@ const char haikus[][4][50] = { {"reaching into sky\n","the girl breaks the wish -\n","bone of geese\n","Raymond Roseliep\n"}, {"in a dark bag\n","onions\n","sprouting\n","Jennifer Virgil\n"}, {"still lake -\n","a hawk makes off\n","with its image\n","R.E.T. Johnson\n"}, - {"skiers!\n","standing\n","on the wind\n","Larry E. Martin\n"} + {"skiers!\n","standing\n","on the wind\n","Larry E. Martin\n"} }; const int nHaikus = 316; int hptr = 0; // index into that list -const int haikuFrames = 600; // how many frames to show each haiku for +const int haikuFrames = 600; // how many frames to show each haiku for // Haiku draw list char haiku1Str[50]; //haikus get copied into these @@ -331,13 +331,13 @@ char poetStr[50]; char spacesStr[] = " - "; struct item haikuList[] = { - {text,10,0,haiku1Str, 0,0}, // haiku display is centered, as is everything - {text,10,0,haiku2Str, 0,0}, - {text,10,0,haiku3Str, 0,0}, - {text,6,0,BlankLn, 0,0}, - {text,6,0,spacesStr, 0,0}, // poet's name is offset to the right - {text,6,0,poetStr, 0,0}, - {listend,0,0,BlankLn,0,0} + {ItemType::text,10,0,haiku1Str, 0,0}, // haiku display is centered, as is everything + {ItemType::text,10,0,haiku2Str, 0,0}, + {ItemType::text,10,0,haiku3Str, 0,0}, + {ItemType::text,6,0,BlankLn, 0,0}, + {ItemType::text,6,0,spacesStr, 0,0}, // poet's name is offset to the right + {ItemType::text,6,0,poetStr, 0,0}, + {ItemType::listend,0,0,BlankLn,0,0} }; void doHaiku(void) diff --git a/SCTVcode/n_flw.ino b/SCTVcode/n_flw.ino index d197c35..31b9eaf 100644 --- a/SCTVcode/n_flw.ino +++ b/SCTVcode/n_flw.ino @@ -9,8 +9,8 @@ int xor1; // first int of thing to xor with it int xor4; // last int of thing to xor with it char FlwStr[] = "piss\n"; // four letters plus a NL and a 0 -// A whole bunch of four letter words, no juicy ones. -const char* FLWs[] = +// A whole bunch of four letter words, no juicy ones. +const char* FLWs[] = {"abet","able","ably","abut","aced","aces","ache","achy","acid","acme", // "yowl","yuck","yuks","yule","yups","yurt", // "zags","zany","zaps","zeal","zees","zerk","zero","zest","zigs","zinc", @@ -20,10 +20,10 @@ int FLWLen = sizeof(FLWs); // Four letter word draw list struct item flwList[] = { - {text,40,0,FlwStr,0,0}, // the nasty word itself - {listend,0,0,BlankLn,0,0} + {ItemType::text,40,0,FlwStr,0,0}, // the nasty word itself + {ItemType::listend,0,0,BlankLn,0,0} }; void MakeFLW() { - strcpy(FlwStr, (char*)&(FLWs[1])); + // strcpy(FlwStr, (char*)&(FLWs[1])); } diff --git a/SCTVcode/p_pong.ino b/SCTVcode/p_pong.ino index 2a5d9a1..fe69a4a 100644 --- a/SCTVcode/p_pong.ino +++ b/SCTVcode/p_pong.ino @@ -1,7 +1,7 @@ // ------------------------------------ Pong game ----------------------------------- // Pong variables -const int courtSize = 2000; +const int courtSize = 2000; const int ballSize = 80; const int paddleLength = 200; const int leftWall = -courtSize/2; @@ -29,13 +29,13 @@ int rScore = 0; char lScoreStr[] = "00"; char rScoreStr[] = "00"; struct item pongList[] = { - {text,10,0,lScoreStr, leftWall/2-100, topWall+scoreHeight}, - {text,10,0,rScoreStr,rightWall/2-100, topWall+scoreHeight}, - {listend,0,0,BlankLn,0,0} + {ItemType::text,10,0,lScoreStr, leftWall/2-100, topWall+scoreHeight}, + {ItemType::text,10,0,rScoreStr,rightWall/2-100, topWall+scoreHeight}, + {ItemType::listend,0,0,BlankLn,0,0} }; -// This plays Pong. It uses the position controls as paddles. +// This plays Pong. It uses the position controls as paddles. void doPong() { // read the position controls for paddles, and average many for smooth readings @@ -57,17 +57,17 @@ void doPong() { // draw the paddles drawALine( leftWall, leftPaddle - paddleLength, leftWall, leftPaddle + paddleLength); drawALine(rightWall, rightPaddle - paddleLength, rightWall, rightPaddle + paddleLength); - - + + // see if the ball hit anything // top or bottom is a simple bounce if ((yBall - ballSize/2) < botWall && yVel <= 0) yVel = -yVel; if ((yBall + ballSize/2) > topWall && yVel >= 0) yVel = -yVel; - + // hit the left player's paddle, so rebound - if (((xBall - ballSize/2) < leftWall + 20) && ((xBall - ballSize/2) > leftWall - 50) && - (xVel < 0) && - yBall < (leftPaddle + paddleLength) && yBall > (leftPaddle - paddleLength) ) + if (((xBall - ballSize/2) < leftWall + 20) && ((xBall - ballSize/2) > leftWall - 50) && + (xVel < 0) && + yBall < (leftPaddle + paddleLength) && yBall > (leftPaddle - paddleLength) ) { xVel = -xVel; // some English @@ -75,52 +75,52 @@ void doPong() { if (yBall < leftPaddle - paddleLength/2) yVel -= 20; } // hit the right player's paddle, so rebound - if (((xBall + ballSize/2) > rightWall - 20) && ((xBall + ballSize/2) < rightWall + 50) && - (xVel > 0) && - yBall < (rightPaddle + paddleLength) && yBall > (rightPaddle - paddleLength) ) + if (((xBall + ballSize/2) > rightWall - 20) && ((xBall + ballSize/2) < rightWall + 50) && + (xVel > 0) && + yBall < (rightPaddle + paddleLength) && yBall > (rightPaddle - paddleLength) ) { xVel = -xVel; // some English if (yBall > rightPaddle + paddleLength/2) yVel += 20; if (yBall < rightPaddle - paddleLength/2) yVel -= 20; } - + // left lpayer missed, ball out of bounds, serve ball again and do some scoring work - if (xBall < leftWall - bounds) + if (xBall < leftWall - bounds) { if (rScore >= 10) // score stops at 11 points in Pong { - rScore = 11; + rScore = 11; waitingForBall = true; waitFrames = 100000; // stop the game by making it wait forever, the user will eventually notice } else { - rScore++; + rScore++; xBall = centerLine; waitingForBall = true; waitFrames = ballStartDelayFrames; } } - + // right player missed, bump left score - if (xBall > rightWall + bounds) + if (xBall > rightWall + bounds) { if (lScore >= 10) // score stops at 11 points in Pong { - lScore = 11; + lScore = 11; waitingForBall = true; waitFrames = 100000; // stop the game by making it wait forever, the user will eventually notice } else { - lScore++; + lScore++; xBall = centerLine; waitingForBall = true; waitFrames = ballStartDelayFrames; } } - // don't do any ball display until ball is ready to release. + // don't do any ball display until ball is ready to release. if (waitingForBall) { if (waitFrames > 0) @@ -148,5 +148,5 @@ void doPong() { lScoreStr[1] = (lScore % 10) | '0'; rScoreStr[0] = (rScore / 10) | '0'; rScoreStr[1] = (rScore % 10) | '0'; - + } diff --git a/SCTVcode/ta_tetris.ino b/SCTVcode/ta_tetris.ino index f340f95..4d626e3 100644 --- a/SCTVcode/ta_tetris.ino +++ b/SCTVcode/ta_tetris.ino @@ -12,7 +12,7 @@ int bucket[20]; -unsigned int last_interaction = 0; // when was the last button pressed? +unsigned int last_interaction = 0; // when was the last button pressed? unsigned int next_tick = 0; // when will the next automatic step happen? int tick_length = 500; // set in reset_tetris() how long does on step take? (decreases on higher levels) @@ -72,16 +72,16 @@ const int TETROMINOES[7][4] = { int positionValue = 0; int rotationValue = 0; -// Drawing the bucket is done in two dimensions. +// Drawing the bucket is done in two dimensions. // The goal is to show an outline of all occupied locations. -// The bucket is scanned in each axis, looking for borders. -// Each border line segment is drawn, taking into account the neighbors. - -// First, the horizontal bars are drawn, based on the borders in the X axis. -// The bucket is scanned horizontally, row by row. -// A line is drawn at the bottom of a row if the row has 1s and the row below has 0s. -// A line is drawn at the top of the row below if the row has 0s and the row below has 1s. -// The start of the line depends on the row contents to the left: +// The bucket is scanned in each axis, looking for borders. +// Each border line segment is drawn, taking into account the neighbors. + +// First, the horizontal bars are drawn, based on the borders in the X axis. +// The bucket is scanned horizontally, row by row. +// A line is drawn at the bottom of a row if the row has 1s and the row below has 0s. +// A line is drawn at the top of the row below if the row has 0s and the row below has 1s. +// The start of the line depends on the row contents to the left: // 00 is left of this col // 11 is right of prev col. @@ -106,10 +106,10 @@ int bsx, bsy, bex, bey = 0; void DrawBucketHorizBars(void) { int it, prev = 0; // the bucket status (0..3) at col,row and col-1, row - + // scan all rows in the bucket, finding any horizontal border lines and drawing them for (int row = 0; row<18; row++) - { + { prev = 0; // col -1 is always empty // if (frame%50 == 0) Serial.printf("row %2d bucket %04X ", row, bucket[row]); for (int col = 0; col < 14; col++) // do one extra column to get the last position displayed @@ -140,10 +140,10 @@ void DrawBucketHorizBars(void) void DrawBucketVertBars(void) { int it, prev = 0; // the bucket status (0..3) at col,row and col, row-1 - + // scan all columns in the bucket, finding any vertical border lines and drawing them for (int col = 1; col < 14; col++) // do one extra column to get the last position displayed - { + { // if (frame%50 == 0) Serial.printf("\n"); prev = 0; // row 0 is always empty for (int row = 0; row<18; row++) @@ -172,7 +172,7 @@ void DrawBucketVertBars(void) } } -// draw the things needed for Tetris. This will eventually have more stuff in it. +// draw the things needed for Tetris. This will eventually have more stuff in it. void drawTetris(void) { Scale = 1; // make them fit! @@ -182,16 +182,16 @@ void drawTetris(void) leftPaddle += analogRead(XPosPin); // read the position controls rightPaddle += analogRead(YPosPin); // make them bipolar so midpoint is nominal } - + // center then in the display area, and scale for the right amount of overshoot // rotation appears to be backwards, so it gets negated // 0..3 is its range, give 3 sets of 4 over knob range - rotationValue = ((40960-rightPaddle)%18000) / 4500 ; - + rotationValue = ((40960-rightPaddle)%18000) / 4500 ; + positionValue = leftPaddle / 4096; // 0..9 is its range if (positionValue > 9) positionValue = 9; if (positionValue < 0) positionValue = 0; - + DispBlock(next_tetr_type, 0, 16, 5); DispBlock(tetr_type, tetr_rotation, tetr_col + 1, tetr_row); DrawBucketHorizBars(); @@ -201,6 +201,6 @@ void drawTetris(void) // Tetris draw list just does the score. Court is drawn by drawTetris(). char scoreStr[] = "00000"; struct item tetrisList[] = { - {text,10,0,scoreStr,800, 0}, - {listend,0,0,BlankLn,0,0} + {ItemType::text,10,0,scoreStr,800, 0}, + {ItemType::listend,0,0,BlankLn,0,0} }; diff --git a/SCTVcode/w_menus.ino b/SCTVcode/w_menus.ino index 83c9b8d..5c10ce0 100644 --- a/SCTVcode/w_menus.ino +++ b/SCTVcode/w_menus.ino @@ -1,6 +1,6 @@ // ------------------------ Menus -------------------------- -// Parameters that are modified in menus +// Parameters that are modified in menus const int ModCen = 1; const int ModYrs = 2; const int ModMon = 3; @@ -28,53 +28,53 @@ char setTimDat[] = "Set Time & Date\n"; char setLocale[] = "Set Locale\n"; char setFLW[] = "Set FLW\n"; struct item mainMenu[] = { - {menu,10,MainDCod,DoneStr, 0,0}, - {menu,10,TimMCod,setTimDat ,0,0}, - {menu,10,LocMCod,setLocale, 0,0}, -//{menu,10,FlwMCod,setFLW, 0,0}, // not used yet - {listend,0,0,BlankLn,0,0} + {ItemType::menu,10,MainDCod,DoneStr, 0,0}, + {ItemType::menu,10,TimMCod,setTimDat ,0,0}, + {ItemType::menu,10,LocMCod,setLocale, 0,0}, +//{ItemType::menu,10,FlwMCod,setFLW, 0,0}, // not used yet + {ItemType::listend,0,0,BlankLn,0,0} }; // The time setting menu struct item timeMenu[] = { - {menu ,10,TimDCod,DoneStr, 0,0}, - {field,10,ModHrs, HrsStr, 0,0}, - {text ,10,0, ColStr, 0,0}, - {field,10,ModMin, MinStr, 0,0}, - {text ,10,0, ColStr, 0,0}, - {field,10,ModSec, SecStr, 0,0}, - {field,10,ModCen, CenStr, 0,0}, // just for completeness - {field,10,ModYrs, YrsStr, 0,0}, - {text ,10,0, DashStr, 0,0}, - {field,10,ModMon, MonthStr,0,0}, - {text ,10,0, DashStr, 0,0}, - {field,10,ModDay, DayStr, 0,0}, - {listend,0,0,BlankLn,0,0} + {ItemType::menu ,10,TimDCod,DoneStr, 0,0}, + {ItemType::field,10,ModHrs, HrsStr, 0,0}, + {ItemType::text ,10,0, ColStr, 0,0}, + {ItemType::field,10,ModMin, MinStr, 0,0}, + {ItemType::text ,10,0, ColStr, 0,0}, + {ItemType::field,10,ModSec, SecStr, 0,0}, + {ItemType::field,10,ModCen, CenStr, 0,0}, // just for completeness + {ItemType::field,10,ModYrs, YrsStr, 0,0}, + {ItemType::text ,10,0, DashStr, 0,0}, + {ItemType::field,10,ModMon, MonthStr,0,0}, + {ItemType::text ,10,0, DashStr, 0,0}, + {ItemType::field,10,ModDay, DayStr, 0,0}, + {ItemType::listend,0,0,BlankLn,0,0} }; // The locale setting menu does DST, time zone, 12/24 hour select char zoneGMT[] = "Zone: GMT"; char hourMode[] = " hour mode\n"; -char DSTlin[] = "DST "; +char DSTlin[] = "DST "; char Hzlin1[] = "Mains: "; char Hzlin2[] = " Hertz\n"; struct item locMenu[] = { // {text ,10,0, BlankLn, 0,0}, - {menu ,10,MainCod, DoneStr, 0,0}, - {text ,10,0, zoneGMT, 0,0}, // Start of time zone text - {field,10,ModZone, ZoneStr, 0,0}, // timezone sign and hours - {text ,10,0, ColStr, 0,0}, - {field,10,ModZmin, ZMinStr, 0,0}, // timezone minutes - {text ,10,0, BlankLn, 0,0}, - {field,10,ModHrSel,HrSelStr, 0,0}, // 12 or 24 - {text ,10,0, hourMode, 0,0}, // hour mode - {text ,10,0, DSTlin, 0,0}, // Daylight string - {field,10,ModDST, DSTStr, 0,0}, // gets "on" or "off" - {text ,10,0, Hzlin1, 0,0}, // Hertz string - {field,10,ModHz, HzStr, 0,0}, // gets "50" or "60" - {text ,10,0, Hzlin2, 0,0}, // Hertz string - {listend,0,0,BlankLn,0,0} + {ItemType::menu ,10,MainCod, DoneStr, 0,0}, + {ItemType::text ,10,0, zoneGMT, 0,0}, // Start of time zone text + {ItemType::field,10,ModZone, ZoneStr, 0,0}, // timezone sign and hours + {ItemType::text ,10,0, ColStr, 0,0}, + {ItemType::field,10,ModZmin, ZMinStr, 0,0}, // timezone minutes + {ItemType::text ,10,0, BlankLn, 0,0}, + {ItemType::field,10,ModHrSel,HrSelStr, 0,0}, // 12 or 24 + {ItemType::text ,10,0, hourMode, 0,0}, // hour mode + {ItemType::text ,10,0, DSTlin, 0,0}, // Daylight string + {ItemType::field,10,ModDST, DSTStr, 0,0}, // gets "on" or "off" + {ItemType::text ,10,0, Hzlin1, 0,0}, // Hertz string + {ItemType::field,10,ModHz, HzStr, 0,0}, // gets "50" or "60" + {ItemType::text ,10,0, Hzlin2, 0,0}, // Hertz string + {ItemType::listend,0,0,BlankLn,0,0} }; @@ -86,7 +86,7 @@ struct item locMenu[] = { const int NClks = 8; // number of clock faces to choose from (splash doesn't count) // list of clock face draw lists -item * ClkList[] = +constexpr const item* ClkList[] = {faceList, // analog clock face, needs hands drawn pongList, // play Pong, special code is run for this tetrisList, // play Tetris @@ -133,8 +133,8 @@ void DoMenuFunc(int func) { // Do a field modification, rolling over to other end on limits -// These are chars for now, which are unsigned, so the subtractions are weird. -// These maybe ought to be ints. +// These are chars for now, which are unsigned, so the subtractions are weird. +// These maybe ought to be ints. void DoModFunc(int func) { switch (func) { case ModCen: @@ -173,7 +173,7 @@ void DoModFunc(int func) { break; case ModMin: - Mins = Mins + EncDir; + Mins = Mins + EncDir; if (Mins > 59) Mins -= 60; if (Mins < 0) Mins += 60; writeRTCtime(); // save the updated time into the DS3232 @@ -219,7 +219,7 @@ void DoModFunc(int func) { JifTick = 5; HalfSec = 30; } - else + else { Hertz = 50; JifTick = 6; @@ -253,13 +253,13 @@ void ModMenu() { } // Navigate the menus via encoder commands -void DoMenus() +void DoMenus() { if (InField) // processing a parameter field { - if (EncDir) // knob turned, + if (EncDir) // knob turned, { - if (InParam) + if (InParam) DoModFunc(MenuCod); // modify parameter value for this field else ModMenu(); // move to next field @@ -273,7 +273,7 @@ void DoMenus() } else InParam = true; // enter parameter-changing mode, blinks field - } // EncDir + } // EncDir } else // not InField, check for menu navigation { diff --git a/SCTVcode/z_main.ino b/SCTVcode/z_main.ino index d35a639..580f0b0 100644 --- a/SCTVcode/z_main.ino +++ b/SCTVcode/z_main.ino @@ -1,14 +1,10 @@ // ----------------------------- Main startup code ------------------------------ -void setup() +void setup() { analogWriteResolution(12); // Use the real DACs for X and Y position - + // Circle lookup tables - for (i=0;iidVendor(), drivers[i]->idProduct()); driver_active[i] = true; @@ -111,7 +107,7 @@ void loop() // If this is a new Serial device, start it up at NMEA buad rate Serial.printf("Connect before begin\n"); - if (drivers[i] == &userial) + if (drivers[i] == &userial) { userial.begin(usbBaudRate); } @@ -126,7 +122,7 @@ void loop() if ((theClock != 1) && (theClock != 2)) // Pong and Tetris use position controls as paddles { xPos = yPos = 0; - for (i=0;i<40;i++) { + for (size_t i = 0; i < 40; i++) { xPos += analogRead(XPosPin) - 512; // read the position controls yPos += analogRead(YPosPin) - 512; // make them bipolar so midpoint is nominal } @@ -135,26 +131,26 @@ void loop() } getTheTime(); // read whichever clock is correctest, make it be local time - + blinkCount++; Blink = (blinkCount >> BlnkBit) & 1; // a one bit, 5 times a second thingie - + DoEnc(); DoButt(); - if (InMenu) + if (InMenu) { DoMenus(); // if menu, process it pushed = false; EncDir = 0; } - else + else { // it's a clock, not a menu - if (EncDir != 0) + if (EncDir != 0) { // If knob turned, choose the next clock face theClock += EncDir; if (theClock >= NClks) theClock = 0; // select the next clock face if (theClock < 0) theClock = NClks - 1; - if (theClock == 1) + if (theClock == 1) { lScore = 0; // reset the score when entering Pong rScore = 0; @@ -172,7 +168,7 @@ void loop() if (theClock == 0) DrawClk(); // clock 0 has hands to draw if (theClock == 1) doPong(); // clock 1 is Pong if (theClock == 2) drawTetris(); // clock 2 is Tetris - if (pushed) + if (pushed) { whichList = mainMenu; HotItem = 1; @@ -204,7 +200,7 @@ void loop() } lastMicros = micros(); // for next time - // if (frame%20 == 0) Serial.printf("strings %4d center %4d draw %6d us\n", + // if (frame%20 == 0) Serial.printf("strings %4d center %4d draw %6d us\n", // stringsTime-beforeTime, centerTime-stringsTime, drawTime-centerTime); frame++; // turn off diagnostic printing }