Ah, you're a script kiddie? Can't work from an algorithm's description but have to poke at someone else's "finished code"? (always fun handing folks a BLANK sheet of paper in an interview and watching them struggle to figure out how to get started!)
Never claimed I knew anything - just enough to get by Never took coding training courses or anything
Err, I meant real, compileable/assembleable code mapped to a specific microcontroller - not pseudocode, much like the actual schematics for the discrete implementation...
Ah, you're a script kiddie? Can't work from an algorithm's description but have to poke at someone else's "finished code"? (always fun handing folks a BLANK sheet of paper in an interview and watching them struggle to figure out how to get started!)
Attached is something that should work -- assuming there are no typographical errors (I just wrote it in Notepad so nothing to check syntax, unresolved symbols, etc. so I fully expect there to be apparently ambiguous SOME_SYMBOL, SomeSymbol and SOMESYMBOL instances).
Note that there are:
no interrupts involved
no counter/timers
no "I/O" instructions
two input pins (SWITCH and LFC) and one output pin (LAMP)
nothing more expensive than integer add/subtract at runtime
a maximum stack penetration of just a few words (3?)
minimum CPU frequency required is probably 20KHz (but I'll need to cycle count to get a real figure)
trivial to add features like an "early warning blink" for the last few seconds before timeout
easily ported to a variety of different processors without changing the algorithm
switch debounce not included (but a trivial addition)
I guesstimate it consumes about 400 bytes of ROM and 35 bytes of RAM (including the stack). Nothing there besides bare metal -- no "helper routines", etc. With a little bit of effort, you should be able to trim 30% of the RAM away.
Once you understand the approach, you'd have no problem porting it to a PIC12, for example (an excellent way to test your understanding as the PIC12's have an unusual programming model). An ATtiny would be a good alternate choice.
[I was going to code for an 8x305 but figured that would be too brutal of an example for most folks to follow; and virtually impossible for folks to find viable tools!]
I will attempt to locate an appropriate assembler/linkage editor tomorrow; today was "goodie day" so I've spent the last 10 hours trying to integrate a fair bit of new kit and don't have access to my software development workstation until I finish these additions. I'd like to be able to discard the kit that's being replaced, ASAP (i.e., tomorrow) so that's the priority!
Ok guys, made a bit of progress on my own. Here's the (incomplete !) code. Let me know if you can open INO files or I need to paste it as plain text. What I managed to achieve so far is the long press to happen once and only once, then stopping that with a short press until the long press can be performed again. Now I need to figure out how to create a countdown and then plop that into the "short press action". There's also that buzzer I was mentioning just because It's probably a messy and amateurish code but it gets the job done so far and doesn't seem to glitch, though as some of you pointed out, something may eventually overflow and mess up....that's what testing is for, it's a work in progress
Err, I meant real, compileable/assembleable code mapped to a specific microcontroller - not pseudocode, much like the actual schematics for the discrete implementation...
The actual issue was that I misread the poorly written datasheet that it could generate an interrupt on both transitions... literally. Other than that, yes the code was written to handle all timing functions simultaneously.
Except that I don't get paid to write this, so it gets backburnered. But with all these opinions, just like the previous post challenge: let's see some actual code and not just ideas! Or are you just the same: no pay no write?
(Mainly this is demonstrating that writing code isn't as trivial as the all-hardware solution.)
Post #144 in this thread represents most of my implementation.
STATE, On and OrElse are macros that just generate data tables from the arguments that they are presented. E.g., "STATE" takes the name of the state (which is a unique identifier that I've chosen for each state) and creates a label bearing that name. I.e., "The table that defines how state <uniquename> behaves begins here!"
"ON" takes the first argument (name of an event), the name of the "next" state to which control should transfer when that even is detected, and the name of a function (procedure) that should be invoked as the machine transitions from the current state to that "next" state. In a small MCU with a small FSM (< 250 states) with few different events (<250), you could represent each line of the state table as:
byte event; byte next_state; void *function;
ORELSE just gobbles up any events that happen to be signaled while in that state for which a specific ON statement doesn't exist. E.g., if "powerfail" was signaled and you hadn't planned on handling it, the ORELSE eats it and invokes "Consume()" to do something about it (maybe log an error?).
LampOn/Off twiddle whatever I/O is associated with the lamp (in some obvious way).
Signal() just stores the event (argument) someplace where the FSM will see it. We've previously decided that events are just single bytes so this can be a simple byte-wide store.
Kill() does whatever is necessary to keep the named task/job from executing. For a superloop style implementation, this would be akin to setting a boolean variable called RUN_nameofjob to false. Thus, kill(MarkTime) would set RUN_MarkTime to FALSE and, the applicable portion of the superloop would be:
if (RUN_MarkTime) {
LoadTimer(LampTimer,60 seconds)
Yield()
if (LampTimer != 0)
Reschedule()
signal(_TimeOut)
Yield()
}
Likewise, spawn simply enables that boolean flag.
A timing job just removes time from any/all "running" timers each time it has been told that "time has passed" (e.g., a 50/60Hz LFC as illustrated upthread). It makes sure that a timer can never "go negative" so any nonzero value means a timer has NOT yet expired. As such, you can "wait" on a timer simply by checking to see if it is zero (elapsed) or not (pending) -- as can be seen in the test of "LampTimer", above.
The actual issue was that I misread the poorly written datasheet that it could generate an interrupt on both transitions... literally. Other than that, yes the code was written to handle all timing functions simultaneously.
Except that I don't get paid to write this, so it gets backburnered. But with all these opinions, just like the previous post challenge: let's see some actual code and not just ideas! Or are you just the same: no pay no write?
(Mainly this is demonstrating that writing code isn't as trivial as the all-hardware solution.)
dang, i feel like finishing my code... but so many options already on the table, or rather, post...
Yeah I ended up using a state machine model, alas I made a wrong assumption on capabilities of the target chip when I was mapping to actual code so I stopped trying. I was targeting straight gcc, not arduino, so I don't get nice cooked timing and button macros...
IME, it's best to implement a timing service instead of trying to hack the code to "do two things at once". It's rare for an algorithm to really want to stop and wait for a timer -- you usually want the timer to run concurrent with <whatever> and just signal <whatever> when it has expired.
Of course, you can watch a hardware counter/timer -- letting the hardware act as the (concurrent) timing service -- but that consumes a hardware resource, often better used for some other purpose.
So, you need an environment that supports multitasking, even in a crude form. It's easiest to do this with assembly language on bare metal as HLL's will require you to know many specific details of the implementation to be able to successfully subvert them (cuz HLL's aren't designed to be share a thread).
Thankfully, you can write multitasking executives that only use a few dozen bytes of code and virtually no RAM... (but, when the applications grow to ~100KB, the HLL approach tends to be a much bigger win, justifying a more fulfledged MTOS).
You still seem to be picking at details that do not affect all designs.
I'm not trying to address "all designs". Rather, I'm explaining an approach that gives you capabilities and economies that are simply not available with crystals/resonators/xtal oscillators.
I design embedded systems so all of my designs have to "do" something (i.e., they don't just "add numbers" for display on a monitor or process files on a disk). Time plays a crucial role in almost all of the acquisition and control subassemblies -- especially when you're pinching pennies (e.g., give me a 24 bit A/DC for less than a dollar in tiny quantities)
Crystals are cheap and you need one for the microcontroller anyway, not like you can omit it, so use what you already have available. For line frequency, you have additional costs detailed later.
Ah, but you don't need one for the MCU! You can use the crappy internal oscillator or even an RC. You only need to ensure that the MCU executes instructions fast enough for your application. You don't care if two units coming off the assembly line operate at two different frequencies; just so long as they both run fast enough for the application and within the operating specifications of the circuit you've designed.
You're missing the point here. When someone wears a watch, the watch is very warm. When the watch isn't worn, it stays cold. If there is a temperature dependence, having it one way or another will exasperate the problem.
No, when the watch is NOT being worn, it stays "room temperature". Room temperature is usually only 20-30 degrees difference from body temperature. I don't know anyone who takes off their watch and leaves it outside in a snowbank while they go into their room-temperature home!
By contrast, a "timed light" might be sited outdoors or in a location that isn't intended to be inhabited 24/7/365. It may experience temperature ranges of 50 degrees each day and 100 degrees (or more) over the variation in seasons.
Again you need to pay attention to your code. Even if you use line frequency you still have to be careful you don't miss an interrupt for whatever reason if your code is busy doing something else.
Does using a crystal absolve you of this responsibility?
What if someone travels abroad and uses it in a country that doesn't have the same line frequency? You have the same problem and still need to change the design to take it into account. Not only that, a crystal based time element doesn't care if you're in a 50 or 60Hz environment.
Ah, my designs are already operating internationally and none have a "please select your country of operation" setting. By looking at the actual line frequency, I can ensure the code adapts to it without requesting that information from the user (how do you set the refresh frequency of your displays to minimize beat against local lighting without knowledge of the mains frequency?)
I can use the actual, instantaneous line frequency to adjust sampling algorithms in sensitive front ends to minimize "AC hum" biasing the data I'm dynamically collecting from my sensors -- without having to design quieter front ends, add shielding, ask the user for the current mains frequency (and hope it doesn't change from cycle to cycle). I have medical instruments that operate reliably in third world countries where primary power may be supplied by a genset -- so there are only nominal frequencies to design against; you have to respond to the actual frequency you're encountering now.
If something is dependant on line frequency, then the software is smart enough to compensate -- or, not depend on it!
It's up to you if you require your timing circuits to be tethered to the wall, but crystals are accurate and stable enough for most purposes to even be run on battery power. (Also note that most power providers don't guarantee cycle for cycle time accuracy, only that there will be about 4320000 or 5184000 cycles per day depending on locale.)
How is that a problem? Counting is easy! Knowing the instantaneous mains frequency has proven so much of an asset, over the years, that I add facilities to systems that don't have direct access to the mains so that they can get this information (in real time) from something that does.
My "time of day" algorithm uses the AC mains over the long term to determine the frequency of the XTAL and the XTAL, in the short term, to specify short time periods -- as well as estimate the passage of time in the absence of power (e.g., if an RTC claims a certain amount of time has elapsed, the software, when the CPU is once again available, can scale that elapsed time based on its knowledge of what the RTC's XTAL frequency was observed (over the course of days, weeks, months, ...) to be.
You also require another input pin to the microcontroller which may be at a premium.
Of course! Hence making sure that I can get a lot of added value from that signal: power available, nominal line frequency, actual line frequency, zero crossings, peak mains voltage, etc.
I'd rather "look ahead" of the power supply to see what will be happening to my "regulated power" in the near future than wait until that power starts to sag (or, worse, have to build in extra hold time so I can scurry to get my last minute housekeeping done as the supply starts to fail (any such sense would require a pin -- unless you rely on the brownout detector in some MCU's)
All an XTAL gives you is a sense of "time".
If having to be connected to the wall is bad enough, you may also need to add in isolation to ensure protection from shock hazard which will also increase the BOM.
If you're powered from the mains, then you're already isolated. You can almost always gain access to the AC mains on the isolated side by carefully considering the design of the power supply. But, you have to approach each product holistically and not as a bunch of "isolated" subsystems that interact on narrow interfaces.
[I have products where the MCU actually acts as the switchmode power supply controller in the power supply that sources its power!]
Ultimately these are all still design tradeoffs.
Of course! Engineering is the art of making value-preserving tradeoffs. Unfortunately, too often, folks opt for the "obvious" approaches and accept their shortcomings without question -- when other approaches can afford more capabilities.
E.g., if the OP decides he wants the light to dim up/down, he'll have to redesign his hardware if he's not made the AC mains signal observable. In my approach, it's just a software mod to drive the triac's gate at a particular time, relative to the mains' zero-crossing.
You are conflating accuracy and stability. They are not the same.
Crystals are also very stable. It's not like we're working with RC oscillators.
I thought the goal here was cheap? I didn't realize the OP could afford a TCXO for his light timer...
Crystals are cheap and you need one for the microcontroller anyway, not like you can omit it, so use what you already have available. For line frequency, you have additional costs detailed later.
And, watches, even when not being worn, seldom experience a wide range of temperature variations. By contrast, the light on my back porch experiences almost 100 degrees of variation over the course of four seasons (easily 50 degrees on any given day). The indoor temperature of my home seldom varies by more than 10 degrees (F) and is usually within 25 degrees of my wrist's temperature.
You're missing the point here. When someone wears a watch, the watch is very warm. When the watch isn't worn, it stays cold. If there is a temperature dependence, having it one way or another will exasperate the problem.
Also note that ceramic resonators (less expensive than an XTAL) are typically thousands of ppm. XTALs (i.e., not "oscillator modules") also exhibit sensitivity to things like humidity, poor PCB cleaning, etc. And, folks often "pull" the XTAL off it's fundamental by poor choice of support components/bias/etc. I've seen cases where designs reliably (yet undesireably!) operated in an overtone mode -- evident because all of the timing was (way!) off.
These are all poor design and assembly techniques, nothing wrong with a crystal that was selected and designed properly.
Yet, your reliance on the internal oscillator necessitates having a timer that can be (at least partially) dedicated to timekeeping. And, if that resource is shared with some other activity, its a prime spot for bugs to creep into the codebase when the timekeeping needs conflict with the "other" use of the timer.
Again you need to pay attention to your code. Even if you use line frequency you still have to be careful you don't miss an interrupt for whatever reason if your code is busy doing something else.
And, you don't have to rely on the developer updating some manifest constant in the codebase when/if the parts list is changed in manufacturing (to use a different device or "timing component")
What if someone travels abroad and uses it in a country that doesn't have the same line frequency? You have the same problem and still need to change the design to take it into account. Not only that, a crystal based time element doesn't care if you're in a 50 or 60Hz environment.
I find having a LFC in my designs almost always adds value (at the very least, it gives me advanced warning of a loss of power so I don't find my FLASH being corrupted due to an outage that happens as I'm updating it).
It's up to you if you require your timing circuits to be tethered to the wall, but crystals are accurate and stable enough for most purposes to even be run on battery power. (Also note that most power providers don't guarantee cycle for cycle time accuracy, only that there will be about 4320000 or 5184000 cycles per day depending on locale.) You also require another input pin to the microcontroller which may be at a premium. If having to be connected to the wall is bad enough, you may also need to add in isolation to ensure protection from shock hazard which will also increase the BOM.
Ultimately these are all still design tradeoffs. If one needs to detect power loss anyway, then you might well use the data from the wall.
It's most pleasing when a post spawns entire lectures on others devices and components and you get the chance to learn like a bit of crash-course - really informative stuff !
You can often get lots of "added value" from what appear to be trivial changes to a design approach.
For example, the line frequency clock can provide:
an indication that power is available
Products that support battery-backed operation often need to know when they are relying on their (fixed!) battery reserves and when primary power is available (e.g., to control charging circuits).
an indication of the nominal mains frequency
are we operating with 50Hz mains or 60? This can be used to adjust display refresh rates (e.g., to minimize "beating" in the display against the flicker of the ambient lights)
an indication of the actual, instantaneous mains frequency
this can be used to frequency lock sampling algorithms to improve noise rejection ("AC hum") in high impedance acquisition circuits
an early warning indication of impending power failure
so the software doesn't undertake an operation that could have costly consequences if interrupted (like updating FLASH); or, so the software can undertake an operation that has been previously deferred for efficiency/economy/durability (like storing parameters in nonvolatile memory that has a fixed number of write cycles before "wear out")
keeping time and time-related actions
already discussed
monitoring mains voltage
measuring the duty cycle of the LFC signal can (depending on design) give you an idea as to the actual peak voltage of the AC mains (higher duty cycle correlates with higher peak voltage as you're "slicing" the AC waveform and finding it "wider" at a particular fixed point)
mains phase information
the LFC can tell you when the zero-crossing occurs and enable you to control (or sense) relative to that actual point in time (think: SCR gate control for dimmers)
other characteristics of the mains
E.g., if the mains voltage (see above) and frequency (see above) are highly variable, you might decide you are operating in an unreliable environment. Or, that other "nasty" loads are present on the same branch circuit that potentially compromise some aspect of your operation. (for example, a UPS being fed by a flakey branch circuit will be perpetually switching in and out thinking that the mains are in the process of failing)
???
Until you think about what you can do with a particular approach (instead of limiting it to your initial goal -- or, prematurely ruling it out!), you won't know what opportunities a particular design approach can provide!
timing is not important, it's just to turn on a lamp long enough to go down/up a flight of stairs - we arent making a bomb or an alarm clock!
ROTFLMFAO! Timing is the very essence of this application!
If the design goal is:
Let me explain: you press the button, the light stays on for some amount of time You press AND hold the button (for say some other amount of time), the light stays on permanently. If the light is already on, regardless of which of the above states, pressing the button will turn it off. Simple right ?
Then I can satisfy it in a matter of seconds -- by handing you a CARDBOARD box with a black circle drawn on the top labeled "button". You can freely "press" it and the light (which I've opted not to include in the design because I've found it superfluous) will come on -- after some amount of time (that I've decided should be 2 minutes longer than the user's actual lifetime).
And, I guarantee that the second activation of that button will extinguish the lamp (that doesn't exist) -- sooner or later!
Time appears:
- in the switch debouncing algorithm (cuz that button most likely doesn't come on/off cleanly but, rather, makes several make/break cycles as it is actuating and/or releasing)
- in the discrimination of "short press" vs. "long press"
- in the determination of the "illumination period"
It could also, potentially, come into play in a "stuck button" detector (i.e., a button that appears to be shorted) or in an "open button" detector (e.g., if you expect the button to be pressed every day or so and haven't seen it pressed in weeks!) .
If you opt to add some "effects" to the lighting or extinguishing of the light (e.g., bringing it up to full intensity, slowly, and similarly dimming it back to extinguished), then it would play into the timing of those effects as well as the control of the firing angle of the SCR driving the lamp.
It's most pleasing when a post spawns entire lectures on others devices and components and you get the chance to learn like a bit of crash-course - really informative stuff !
Crystals are specced to number of PPM, which is extremely accurate for over long periods of time.
You are conflating accuracy and stability. They are not the same.
Most of the time the crystal inaccuracy is because of either selecting cheap crystals, bad circuit design like omitting or having too much capacitance on wires, damage by bad soldering, or even badly written software. Otherwise good crystals are very accurate if it's designed carefully.
I thought the goal here was cheap? I didn't realize the OP could afford a TCXO for his light timer...
Also note people do not necessarily wear their watches 24/7, would accuracy be lost when removed?
Accuracy != stability. And, watches, even when not being worn, seldom experience a wide range of temperature variations. By contrast, the light on my back porch experiences almost 100 degrees of variation over the course of four seasons (easily 50 degrees on any given day). The indoor temperature of my home seldom varies by more than 10 degrees (F) and is usually within 25 degrees of my wrist's temperature.
Usually crystals also are specced for PPM per temperature change too, which also is very low. I have a watch that has kept time for several years without being worn or being reset, thanks to a very accurate clock crystal. It finally lost time due to a bad CR2016, they sure do not last forever.
Watch makers have invested a fair bit of effort into optimizing their 32768Hz XTALS by carefully controlling things like cut angle. And, it's unlikely that you've kept your watch stored out in the (unheated) garage for all that time. Wanna bet its been at 98.6 or ~75 degrees for most of its life?
Also note that ceramic resonators (less expensive than an XTAL) are typically thousands of ppm. XTALs (i.e., not "oscillator modules") also exhibit sensitivity to things like humidity, poor PCB cleaning, etc. And, folks often "pull" the XTAL off it's fundamental by poor choice of support components/bias/etc. I've seen cases where designs reliably (yet undesireably!) operated in an overtone mode -- evident because all of the timing was (way!) off.
You also need to consider that there has been consideration to cheapen the cost of energy by no longer enforcing 50/60Hz AC mains frequency from power plants as fewer and fewer time elements are dependent on AC power and instead reliant on internet, WWVB, or even a crystal to keep parts count down so the same circuit can be used when on battery power. How many people still use synchronous motor clocks anymore? (How many people can still tell time on 2-hand clocks?)
Is the LIGHT that is being controlled also powered by batteries?
But this is all moot, the accuracy (and precision) of this light timer has no problem being within even 5%.
Then your arguments against the stability of the AC mains falls away.
Yet, your reliance on the internal oscillator necessitates having a timer that can be (at least partially) dedicated to timekeeping. And, if that resource is shared with some other activity, its a prime spot for bugs to creep into the codebase when the timekeeping needs conflict with the "other" use of the timer.
And, you don't have to rely on the developer updating some manifest constant in the codebase when/if the parts list is changed in manufacturing (to use a different device or "timing component")
I find having a LFC in my designs almost always adds value (at the very least, it gives me advanced warning of a loss of power so I don't find my FLASH being corrupted due to an outage that happens as I'm updating it).
Crystals are specced to number of PPM, which is extremely accurate for over long periods of time. Most of the time the crystal inaccuracy is because of either selecting cheap crystals, bad circuit design like omitting or having too much capacitance on wires, damage by bad soldering, or even badly written software. Otherwise good crystals are very accurate if it's designed carefully.
Also note people do not necessarily wear their watches 24/7, would accuracy be lost when removed? Usually crystals also are specced for PPM per temperature change too, which also is very low. I have a watch that has kept time for several years without being worn or being reset, thanks to a very accurate clock crystal. It finally lost time due to a bad CR2016, they sure do not last forever.
On the other hand, if you're using the onchip clock source inside newer microcontrollers, these however can be off by a few percent, these are nowhere near as accurate as actual crystals.
You also need to consider that there has been consideration to cheapen the cost of energy by no longer enforcing 50/60Hz AC mains frequency from power plants as fewer and fewer time elements are dependent on AC power and instead reliant on internet, WWVB, or even a crystal to keep parts count down so the same circuit can be used when on battery power. How many people still use synchronous motor clocks anymore? (How many people can still tell time on 2-hand clocks?)
But this is all moot, the accuracy (and precision) of this light timer has no problem being within even 5%.
this is not just a timer, it's a remote controlled timeswitch with override facility.
Doesn't matter. The reference for the timekeeping portion of the algorithm is the issue addressed by the line frequency clock. You can use the LFC to drive a time-of-day clock, a timer, or set the blink rate of some XMAS lights. The point is that it is already there and isn't going to vary with temperature, etc.
Let me explain: you press the button, the light stays on for 60 seconds (a minute if you prefer). You press AND hold the button (for say a second), the light stays on permanently. If the light is already on, regardless of which of the above states, pressing the button will turn it off. Simple right ?
And that's exactly what my sample code does -- except I have decided that the press to turn it off (if it is in "latched on" mode) must be of short duration. This is an arbitrary restriction -- but one that I feel makes sense.
Light has come on because you pressed the button "briefly". You have no way of knowing that this is the case -- you will only know, for sure, in ~60 seconds (if the light goes OFF, then the circuit must have thought you only pressed it briefly... whether that was your intention, or not; if it stays ON, then you must have pressed it "longer").
If you want to force the light to STAY on, even though you initially only wanted it to turn on for 60 seconds, I'm suggesting you should be forced to press it for a long duration -- just like you would have when it was OFF.
To turn it OFF while it is already on, I expect a short press. I.e., the duration of the press while ON indicates whether you want it to LATCH on or toggle back off, now.
Why would you use AC mains cycle counting if you're using a microcontroller, if you clock it at 50Hz/60Hz it'd only run 50-60 instructions per second and it would basically be unusably slow. If you're using a crystal with a microcontroller, you might well as use that.
Crystals are notoriously poor in terms of stability (initial, temperature, etc.). Wristwatches have good stability because they are temperature controlled applications (98.6 degrees)
You don't clock the MCU with the AC mains. Rather, you use the AC mains as a reference input. You can then poll it (at some frequency greater than ~100Hz) to recover the actual mains frequency or use it as an edge-triggered interrupt (if MCU has such a facility).
watchLFC() {
if (ACmainsInput == lastACmainsInput) return
lastACmainsInput = !lastACmainsInput
if (lastACmainsInput == HIGH) signal(LineFrequencyClock)
return
}
Now, you have a derived frequency source that, over the long run, will track the frequency of the AC mains. There will be some phase jitter due to the lack of perfect synchronization in the sampling routine, above -- which can be minimized by increasing the sampling frequency.
If you know the nominal line frequency that the device will be operating at (e.g., OP was 50Hz), then you can put a number on your results; e.g., every 50 LFC events translates to 1 second.
If you have to support dual 50/60Hz application, then you can use a grossly imprecise knowledge of your XTAL (which may be ceramic resonator, RC, etc. on low end MCU's) to make a decision as to the apparent line frequency (i.e., count CPU cycles for one or two LFC events and if less than some threshold, decide that the higher line frequency is the case; else the lower)
I use this approach in most of my timekeeping software with a cascaded control loop to exploit the short term stability of the XTAL to compensate for short term variations in the AC mains (in the US, the line frequency is really only stable over long periods of time -- like many hours -- and can have short term deviations)
dang, i feel like finishing my code... but so many options already on the table, or rather, post...
Yeah I ended up using a state machine model, alas I made a wrong assumption on capabilities of the target chip when I was mapping to actual code so I stopped trying. I was targeting straight gcc, not arduino, so I don't get nice cooked timing and button macros...
Leave a comment: