📄 main.c
字号:
/* we get here through POR. All these things need be */
/* initialized only once. */
if ( !WokeFromSleep() ) {
/* initialize port pin default values and modes. */
/* GP0: input Rx data */
/* GP1: input key up */
/* GP2: output serial strobe */
/* GP3: input key down */
/* GP4: output PWM */
/* GP5: output Tx data */
PORT = (GP0_NO_SERIAL_DATA)
| (GP1_NO_SERIAL_CLK)
| (GP2_NO_SERIAL_STB)
| (GP3_NO_KEY_DOWN)
| (GP4_NO_PWM)
| (GP5_RS232_IDLE);
/* these variables are initialized only on power- */
/* up and persist until the system loses power. */
/* .dontSleep: default is to sleep */
/* speed: start speed */
sysStat.dontSleep = 0;
speed = FAN_START_SPEED;
/* set non-default baud rate if selected. */
if ( !keyUP )
oneBitDelay = BAUD_KEY_UP;
else if ( !keyDN )
oneBitDelay = BAUD_KEY_DN;
else
oneBitDelay = BAUD_DEFAULT;
/* initialize Salvo. */
/* required because Salvo's vars are declared as */
/* persistent. */
OSInit();
/* create tasks. For those builds that use task */
/* priorities (not really necessary here), */
/* TaskBeep() must be lowest since it normally */
/* only yields. */
OSCreateTask(TaskReadKeys, TASK_READ_KEYS_P, 1);
OSCreateTask(TaskSpinFan, TASK_SPIN_FAN_P, 2);
OSCreateTask(TaskBeep, TASK_BEEP_P, 3);
}
/* these variables are (re-)initialized on power-up */
/* and wake-up. */
/* .beep: no beeping required */
/* .change: force PWM & bargraph init */
/* .onPWM: PWM output is OFF */
/* .xmitOK: OK to transmit to remote */
/* sleepTimer: reset this counter */
sysStat.beep = 0;
sysStat.change = 1;
sysStat.onPWM = 0;
sysStat.napBit = 0;
sysStat.xmitOK = 1;
sleepTimer = TIME_TO_SLEEP;
/* reset Timer0 prior to entering main loop. This */
/* clears the prescalar, too. */
TMR0 = 0;
/* the usual "infinite for() loop", with extra code to */
/* handle timer and sensing for sleep. */
for (;;) {
/* if Timer0 has rolled over mark it so we can call*/
/* OSTimer. A temporary placeholder for Timer0 is */
/* required because it might change value between */
/* the first and second reads. This is the normal */
/* way the system keeps track of time. */
tmpTMR0 = TMR0;
if ( tmpTMR0 < oldTMR0 ) {
/* call Salvo's Timer to process delayed tasks.*/
OSTimer();
/* time-to-sleep countdown timer runs at */
/* system tick rate. */
if ( sleepTimer )
sleepTimer--;
}
oldTMR0 = tmpTMR0;
/* act on command, if present. Note that this has */
/* no deleterious effect on the command that woke */
/* us up from sleep. */
RcvCmd();
/* if sleep timer times out, then there's been no */
/* no user activity for a while, and it's safe */
/* to shut things down. Wake up on pin change or */
/* incoming RS-232 data. */
/* GPIO pins are in the GPIO_NORMAL_CONFIG mode, */
/* so no housekeeping is necessary. */
if ( !sleepTimer && !sysStat.dontSleep ) {
/* turn off fan, bargraph and beeper. No need */
/* to do anything else, since it will all */
/* be reset on POR/wake-on-pin anyway. */
outPWM = PWM_OFF;
OutBargraph(LEDs[0]);
/* reset woke-up flag. */
ClrWakeFlag();
/* dummy read for proper wake-on-change */
/* operation. */
oldTMR0 = PORT;
/* sleepy time - will wake up on pin change. */
GoToSleep();
}
/* dispatch most eligible task. */
OSSched();
}
}
/************************************************************
**** ****
** **
TaskReadKeys()
Interprets user activity on the two pushbutton keys, and
does key-repeat without acceleration. External action from
RS-232 port is processed here by monitoring sysStat.change
periodically.
** **
**** ****
************************************************************/
void TaskReadKeys ( void )
{
static persistent i; /* persistent to avoid init code */
char tickTockPattern;
/* intialize this once, when task first runs. */
i = NAP_TOCK_PERIOD;
for (;;) {
/* sample keys every 20ms. */
OS_Delay(SAMPLE_PERIOD, TaskReadKeys1);
/* keypress means user wants to wake system and/or */
/* change fan speed. */
if ( !keyUP || !keyDN ) {
/* wait the debounce period. */
OS_Delay(DEBOUNCE_PERIOD, TaskReadKeys2);
/* if keyUP is still pressed, then it's valid. */
/* by not waiting for the key to be released, */
/* we get key-repeat for free! */
if ( !keyUP ) {
/* do keyUP stuff. force beep, etc. even */
/* if speed doesn't change. */
sysStat.change = 1;
if ( speed != PWM_STEPS )
speed++;
}
/* repeat for keyDN. */
else if ( !keyDN ) {
sysStat.change = 1;
if ( speed != 0 )
speed--;
}
}
/* time for some fun -- couldn't leave any free */
/* ROM leftover, after all ... do a two-bit */
/* metronome at 1Hz when the unit is napping. */
if ( !sysStat.dontSleep
&& ( sleepTimer <= (TIME_TO_SLEEP - TIME_TO_NAP) ) ) {
/* countdown timer of SAMPLE_PERIOD. */
if ( --i == 0 ) {
/* reset timer. Note the error in the */
/* nap tock period -- it's compounded */
/* by this multiplier. */
i = NAP_TOCK_PERIOD;
/* tick or tock on bargraph. */
sysStat.napBit ^= 1;
if ( sysStat.napBit )
tickTockPattern = TICK_PATTERN;
else
tickTockPattern = TOCK_PATTERN;
OutBargraph(tickTockPattern);
}
}
/* make necessary changes if the user requested */
/* a change in speed or if an external command */
/* was received. */
if ( sysStat.change ) {
/* reset changed flag. */
sysStat.change = 0;
/* reset sleep timer. */
sleepTimer = TIME_TO_SLEEP;
/* request a beep. */
sysStat.beep = 1;
/* show new speed on LED bargraph. Force */
/* -MON/BEEP low to enable Rx data monitoring.*/
OutBargraph(LEDs[speed]);
/* now send the speed out via RS-232. */
OutRS232(speed | '0');
}
}
}
/************************************************************
**** ****
** **
TaskSpinFan()
Drives the fan at the current fan setting via a PWM.
** **
**** ****
************************************************************/
void TaskSpinFan ( void )
{
OStypeDelay delay;
for (;;) {
/* speed of 0 means fan is completely OFF. No PWM -*/
/* dc only. Revisit in one system tick. */
if ( speed == 0 ) {
delay = ONE_TICK;
outPWM = PWM_OFF;
}
/* speed of PWM_STEPS means fan is completely ON. */
/* No PWM - dc only. Revisit in one system tick. */
else if ( speed == PWM_STEPS ) {
delay = ONE_TICK;
outPWM = PWM_ON;
}
/* intermediate speeds (1 <= speed <= 7) */
/* require PWM action. */
else {
/* If PWM output is OFF, we need to create the */
/* "ON pulse" whose length is directly propor-*/
/* tional to the fan speed. */
if ( !sysStat.onPWM ) {
delay = PWM_EXTRA_PERIODS + speed;
outPWM = PWM_ON;
sysStat.onPWM = 1;
}
/* If PWM output is ON, we need to finish the */
/* PWM period with the output OFF. */
else {
delay = PWM_STEPS - speed;
outPWM = PWM_OFF;
sysStat.onPWM = 0;
}
}
/* PWM port value has been set -- now delay either */
/* 4ms (dc output) or PWM high- or low-cycle. */
OS_Delay(delay, TaskSpinFan1);
}
}
/************************************************************
**** ****
** **
TaskBeep()
Beep by outputting a 4kHz waveform to the beeper for a short
time:
_ _ _ _ _ _ _
_| |__| |__| |__| |__| |__| |__| |________________ etc.
Pulse width is ca. 125us. Checks for the need to beep
every system tick, except when it's in the middle of
beeping. Yields to more important tasks.
NOTE: since no interrupts are used, semaphore management is
very simple ...
** **
**** ****
************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -