It 'does work', piece by piece, in an alarm handler, while another alarm monitors the Profile. When the time spent in alarm handlers becomes too high or low, the Processor is sped up or slowed down accordingly, if possible.
An interaction with this sketch might look like:
w300 Ln 16.424 Workload=300 Ln 17.060 Load: 22%, speed changed to: 36MHz Ln 18.070 Load: 25%, speed changed to: 24MHz w800 Ln 22.922 Workload=800 Ln 24.098 Load: 95%, speed changed to: 36MHz Ln 25.108 Load: 67%, speed changed to: 48MHz w10 Ln 30.467 Workload=10 Ln 31.116 Load: 20%, speed changed to: 36MHz Ln 32.126 Load: 0%, speed changed to: 24MHz Ln 33.146 Load: 1%, speed changed to: 12MHz w1200 Ln 39.719 Workload=1200 Ln 41.188 Load: 92%, speed changed to: 24MHz Ln 42.198 Load: 95%, speed changed to: 36MHz Ln 43.213 Load: 96%, speed changed to: 48MHz Ln 44.225 Load: 82%, speed changed to: 60MHz Ln 45.230 Load: 72%, speed changed to: 72MHz
where we send 'w' packets to alter the workload at various times, provoking dynamic speed changes when the alarm handling load falls outside the 33% - 66% band.
u32 workLoad = 500; // Loops per workloadHandler call void setWorkload(u8 * packet) { u32 arg; if (packetScanf(packet,"w%d\n",&arg) == 3 && arg < 2000) workLoad = arg; logNormal("Workload=%d\n", workLoad); } void workloadHandler(u32 when) { // Alarm handler for 'doing work' u32 sum = 0; for (u32 i = 0; i < workLoad; ++i) // Work, for us, is just sum += random(1000); // adding up random numbers ledSet(BODY_RGB_BLUE_PIN, sum&1); // and maybe lighting an LED.. when += 10; // Do work every 10ms if (IS_EARLIER(when,millis())) when = millis(); // Or ASAP if we're behind Alarms.set(Alarms.currentAlarmNumber(),when); // Reschedule } void processorMonitor(u32 when) { // Alarm handler for controlling processor speed u32 load = Profile.getPPM(TICKER_ALARM_HANDLER)/10000; // Get alarm time, as a percent bool lowLoad = load < 33; // Say under 33% is underloaded bool highLoad = load > 66; // Say over 66% is overloaded ledSet(BODY_RGB_RED_PIN,highLoad); // Display overload condition ledSet(BODY_RGB_GREEN_PIN,lowLoad); // Display underload condition u32 speedCode = Processor.getCode(); // Find out how fast we're running now if (highLoad && speedCode < Processor.getCodeMax()) // If need and have more.. ++speedCode; // More coal to the furnace! Shovel! else if (lowLoad && speedCode > Processor.getCodeMin()) // If need and have less.. --speedCode; // Whoa, nellie.. if (speedCode != Processor.getCode()) { Processor.setCode(speedCode); logNormal("Load: %2d%%, speed changed to: %dMHz\n",load,Processor.getMHz()); } Profile.begin(); // Reset statistics gathering Alarms.set(Alarms.currentAlarmNumber(),millis()+1000); // Do monitoring about 1Hz } void setup() { Profile.begin(); // Start profiling Body.reflex('w',setWorkload); // Create reflex Alarms.set(Alarms.create(workloadHandler),millis()); // Alarm to generate work Alarms.set(Alarms.create(processorMonitor),millis()); // Alarm to monitor load } void loop() { /* Nothing to do */ }