EE 459 Senior Design Project DURACELL DURASAVER By TEAM

advertisement
EE 459 Senior Design Project
DURACELL DURASAVER
By
TEAM 1
Sara Adkins
Paul VanWieren
Robert Whitley
Introduction
Most modern electronic devices consume small amounts of electrical power even when
they have been turned off. This standby power, or “vampire power”, can be a significant portion
of electrical power usage in a typical home. Our power controller is designed to minimize this
wasteful power consumption by providing the user with user-programmable power outlets that
virtually “unplug” devices during non-usage times. A standard application, for example, would
be to program a television to virtually unplug during the typical eight-hour workday, thereby
eliminating its standby power consumption during the portion of the day that it is unused.
Section I: Hardware Design
In order to describe the layout of our project in the most systematic way possible, we
have chosen to break our hardware report into two parts: one for each of the two component
boards (the main module and the RF remote control). Each of these component boards, in turn, is
analyzed using a simple block diagram, whose description is broken into sections outlining each
of the important or interesting components. In order to save space, simple, widely-used
components such as LED’s and the like will not be explained in detail.
Our description begins with the main module board:
Main Module:
Block Diagram:
The following is a block diagram of the hardware layout of the main module:
User input consists of six push-buttons, while user feedback is accomplished using a 24 character
x 2 line LCD. The primary functional outputs of the device are four outlet plugs which allow
virtual unplugging of devices as per the project description. The microcontroller communicates
with the real-time clock through an I2C interface, requiring two bidirectional hardware lines.
There is also a test LED for running test programs on the prototype board. In addition, the
microcontroller receives inputs from a 10MHz clock and a 315MHz RF receiver.
User Input Buttons:
User input to the device is achieved using six buttons to navigate menus, make selections,
and reset the device. The layout of the buttons in shown below.
The four white directional buttons allow the user to progress through the menus. In general, the
left and right buttons move between menus, while the up and down buttons allow changing the
current option within a given menu. The black select button allows the user to select the menu
option currently being displayed. A reset button allows the user to force a hardware reset of the
device.
The input buttons, with the exception of the reset button (which has no need for debouncing) are de-bounced using the following RC circuit network:
This design is an improved version of a well-accepted SPST button de-bouncing scheme. The
initial design did not include the 4.7uF capacitor (values for the resistors and the other capacitor
were not given by the initial design, which was meant as a design template rather than a
complete circuit). However, this initial design has a critical weakness. In order to be able to
effectively “pull down” the signal to an appropriate TTL logic 0, the value of the first resistor
(470 Ohm in our circuit) must be kept very small in relation to the second resistor (10 kOhm in
our circuit). Using the values given in our circuit, in the absence of the larger capacitor, the RC
time constant of the circuit upon closing the switch is roughly 20 times smaller than the time
constant upon opening the switch (due to the two resistors acting in parallel, thus dramatically
decreasing the resistance to AC ground). We found in experiments that the bounce duration of
the button signal was ~2ms regardless of the switch being opened or closed. Thus, use of the
initial circuit would require a closed-switch time constant of at least 2ms, thereby necessitating a
huge open-switch time constant (on the order of 40ms or so). This would greatly reduce the pulse
duration of the button-press, and possibly even eliminate it completely.
In order to address this critical weakness in the initial design, the 4.7uF capacitor was
added to the RC network such that the two capacitances add upon closing the switch. In essence,
when the button is pressed, the large decrease in resistance to AC ground is counteracted by a
large increase in capacitance to AC ground. If we call the open-switch time constant To and the
closed-switch time constant Tc (with similar labels for the resistance and capacitance to AC
ground), the following calculations apply (assuming a Schmitt-trigger inverter with a current
draw of ~0mA and approximately infinite input impedance):
To = RoCo = (10kΩ)(0.22µF) = 2.2 ms
Tc = RcCc = (10kΩ//470Ω)(0.22µF+4.7µF) = (448.9Ω)(4.92µF) = 2.2 ms
Vo = 5V
Vc = 5V*[(470Ω)/(470Ω+ 10kΩ)] = 0.22 V
This switch de-bouncing scheme fulfills the necessary requirements, and it does it for a fraction
of the price of the commonly used EDE2008 button de-bouncing integrated circuit (the
EDE2008 runs about $3.82 per unit if purchased in bulk, while our de-bouncing scheme costs
our board around $0.79 if purchased in bulk).
LCD:
User feedback was accomplished using a 24x2 character LCD display, purchased from
BG micro. Its layout in the main module is shown below.
This LCD was a used part that had been pulled from old equipment. The advantage of this was
that it was very economical ($3.95), but the disadvantage was that the LCD was rather
temperamental (which caused plenty of head-ache in debugging our board). In addition, the
parallel connector was wired backward to the normally accepted fashion for 8-bit parallel LCD
interfaces. The image below displays the connection grid:
This image, as well as plenty of other useful data for getting this LCD to work, can be found at
the following URL:
http://www.serialwombat.com/parts/lcd107.htm
Outlet Outputs:
The primary functional outputs of the main module are the outlet outputs, which are
displayed as components and in the schematic below:
As can be seen from the schematic, we used SPST-NO reed relays to establish a connection on
the AC load line and thus enable the outlet in question. A green LED next to each outlet on the
main module lights up when the outlet is enabled by the microcontroller. Since the current drive
capabilities of the I/O pins of the JL16 are limited, we constructed a simple, single-transistor
amplifier to drive the large amount of necessary current through the relay coils (~170mA of
current drive was achieved using this amplification technique).
Interestingly, the small DIP relays we used were unable to handle the current load of the
AC load simulation board. While the AC load simulator was found to draw ~0.54A of AC
current, the particular relays we used only had contact ratings of 0.5ADC “switching current,” as
demonstrated in the annotated datasheet extract below.
In order to solve this problem (three relays were burnt out completely before we
identified the cause), 10 Ohms of in-series resistance was added to each AC load line connection
in order to limit the AC load current to less than the 0.5A limit (a load current of slightly above
0.4A AC was achieved). This was done by wiring two high-power 5 Ohm resistors in series on
each AC load line (the big pink cylinders in the middle of the red boxed area in the above
figure). While this limited the AC load to an appropriate level, the bulb brightness of the AC
load simulator was still plenty good. This was an imperfect solution (a better solution would
have been to obtain and install more robust relays), but given our time constraints, it was the
most realistic option. The use of more robust relays is covered in the “possible improvements”
section of this report.
RF Receiver:
In order to enable communication with the RF remote control, a 315MHz RF link
receiver obtained from SparkFun electronics was used on the main module board and connected
to the serial receiver port of the microcontroller. The placement of this receiver in the board
layout is shown below.
This IC, in conjunction with the 315MHz transmitter we used on the remote control, is designed
to form a wireless link between two devices. Ideally, whatever data is present as input to the
transmitter data pin will be present as output from the receiver data pin. We found the
performance of these RF link ICs to be moderate at best. In particular, the devices seemed to fall
out of sync if the transmitter data was not made to constantly oscillate. In particular, if the
transmitter data pin was held at a TTL logic 1 for around 50 ms or so, the receiver would fall out
of sync and begin to oscillate wildly at ~60Hz, presumably as a result of power line noise effects.
This would naturally cause the SCI port of the microcontroller to register garbage data. This
problem was partially solved by sending several known transmission characters to the receiver
before the real data was sent. However, we did not have enough time to get the RF link working
perfectly, and its operation is still fidgety. Possible improvements to the RF link mechanism,
which we did not have time to implement this semester, are discussed in the “possible
improvements” section of this report.
Real-Time Clock:
We used a DS1307 real-time clock, in conjunction with a 32kHz oscillator chip, to
provide time information to our board – as did most groups. A 3V battery was attached to both
the RTC and the 32kHz oscillator to provide backup power in the case of a power outage. This
way, the user would not need to re-set the clock after a power outage. The real-time clock, and in
particular its I2C interface, was a source of constant frustration in our programming and debugging efforts. In particular, we believe there may be a problem with the RTC’s acknowledge
bit transmission. However, after much de-bugging and experimentation, we were able to get
accurate time results. In addition, the battery back-up effectively held the clock’s time upon
unplugging and re-plugging the project board.
10MHz Oscillator:
We used a simple DIP oscillator to provide the microcontroller with a 10MHz clock. We
found it unnecessary to do any external shaping of the clock signal, as the oscillator signal was
clean enough to provide the microcontroller with a good functional signal.
Remote Control:
Block Diagram:
In order to provide the user with remote manual override capabilities, we implemented an
RF-enabled remote control that allows the user to manually override the programmed outlet onoff times with a simple button-press. Below is a functional block diagram of the remote control:
User input to the remote control consists of four manual device override buttons and a single
reset button. Naturally, the microcontroller is also provided a 10MHz clock. The primary
functional output of the microcontroller is the 315MHz RF link transmitter. A green power
verification LED was also included on this board, as well as a red test LED for running test
programs (this test LED is not shown in the above functional block diagram).
Power to the board was provided without the need for an external power supply. A 9V
battery holder was mounted on the board, and the output of the 9V battery run through a 5V
regulator to provide TTL-level power to the board.
User Input Buttons:
The diagram below outlines the layout of the four manual override buttons that serve as
the user input to the remote control.
Each of these numbered buttons corresponds to the outlet which, when pressed, it will override.
For ease of construction (because of limited project completion time), we used an EDE2008 DIP
button de-bouncer on our remote control prototype board, as opposed to our custom de-bouncing
scheme developed for the main module board.
RF Transmitter:
To provide the wireless RF link between the main module and the remote control, we
used a 315MHz RF link transmitter from SparkFun electronics. The position of the transmitter in
the board layout is shown in the diagram below:
The functional description of the RF link transmitter/receiver pair is outlined in the “Main
Module” section of this report, under the “RF Receiver” heading. Please see this section for more
information on the theoretical function and the problems associated with this device. As
mentioned before, improvements that could be made to this RF link pair are outlined in the
“Possible Improvements” section.
PCB Implementation of Remote Control:
In order to get more experience with printed-circuit board implementation (the industry
standard for consumer electronics), we designed, ordered, and assembled a custom PCB for the
remote control portion of the project. The PCB was designed using ExpressPCB’s free software
(downloadable online at expresspcb.com). A screenshot of our final board design in the free
software window is shown below.
We used ExpressPCB’s “miniboard” service, which provides three of the same 2.5”x3.8” boards
at around $50 cost (plus tax and shipping). We found the printing and shipping of the board to be
very fast; we ordered our board early in the week and received it at the end of the same week.
We assembled the board without the use of any special surface-mount prototyping tools,
which was rather challenging. Tweezers were used to hold the tiny surface-mount resistors,
switch, and oscillator in place while soldering. All pads were tinned before component
placement for a solid connection. The diagram below gives an idea of the general change in
board layout from prototype to PCB, as well as a qualitative comparison of the relative sizes of
the surface-mount parts in relation to the DIP components.
It may be noted that both the microcontroller and the EDE2008 button de-bouncing IC were
placed on the PCB in DIP packages. It was necessary to use the DIP microcontroller package,
since the zero-insertion-force sockets used in the USB programming devices are designed to hold
these packages. However, the DIP EDE2008 was used for the sake of convenience and time
conservation – these DIP components were readily available from Professor Weber, while we
would have had to order surface-mount components separately.
Section II: Software Design
Memory Considerations
Because of the limited memory space on the JL16 microcontroller, variable declarations
had to be carefully planned. For each LCD menu prompt there was a known string. These were
declared as ‘const’ so that they would be stored in ROM. Similarly, ports that were used often
were defined constants. For example, each button was defined as LEFT, RIGHT, UP, DOWN,
and SELECT for ease of access later in the code so that they wouldn’t need to be referenced with
PTA_PTA1, etc. A similar concept was used to keep track of where things were stored in the
Real Time Clock (RTC).
The DS1307 RTC we used had a 3-volt battery to keep the time even when the board was
powered off, but it also stored 56 bytes of internal RAM non-volatilely. We decided to use these
56-bytes to store the programmable turn-on and turn-off times of our Durasaver such that they
are not lost in the event of a power outage. The 56 bytes divided by 7 days each week and 4
devices leaves 2 bytes per device per day – 1 byte for turn-off and 1 byte for turn-on. However,
1 byte is not enough to store hours (5 bits) in addition to minutes (7 bits), so we designed it so
each programmed time would include an hour (1-12), a 10-minute-interval minute (0-5 to
represent 0, 10, 20, 30, 40, 50), and 1 bit to represent AM/PM. This added up to 4 bits for hour,
3 bits for minute interval, and 1 bit for AM/PM – 8 bits or 1 byte total. We decided that 10minute intervals was sufficient for the needs of this project, since it is easy to round a turnoff/turn-on time to the nearest 10-minute interval, and it is cheaper to utilize the RAM included
with the RTC instead of installing an additional EPROM. Given these 2 bytes per outlet per day,
we had two options for how we could organize their storage in the RTC’s RAM.
One option was to store it organized by outlet. This means that outlet 1’s programmed
times would be stored starting with Sunday’s turn-off time stored at address 0x08. Sunday’s
turn-on time would come next, followed by Monday starting at 0x0A, etc. This definitely got the
job done, but complicated the determination of an address for reading and writing. Since the
monitoring of outlet times in the main loop was based on the current day of the week, that was a
more efficient way by which to organize the RTC RAM for storing programmed times. Below is
a table of the memory map we used for storing the programmed times in the RTC RAM; the
bolded addresses are the ones we stored as constants to keep track of the starting address for each
day of the week:
0x08
Day of the
Week
Sunday
0x09
0x0A
Sunday
Sunday
Address
Outlet
Outlet 1
(off)
Outlet 1 (on)
Outlet 2
(off)
0x0B
0x0C
Sunday
Sunday
0x0D
0x0E
Sunday
Sunday
0x0F
0x10
Sunday
Monday
0x11
0x12
Monday
Monday
0x13
0x14
Monday
Monday
0x15
0x16
Monday
Monday
0x17
0x18
Monday
Tuesday
0x19
0x1A
Tuesday
Tuesday
0x1B
0x1C
Tuesday
Tuesday
0x1D
0x1E
Tuesday
Tuesday
0x1F
0x20
Tuesday
Wednesday
0x21
0x22
Wednesday
Wednesday
0x23
0x24
Wednesday
Wednesday
0x25
0x26
Wednesday
Wednesday
0x27
0x28
Wednesday
Thursday
Outlet 2 (on)
Outlet 3
(off)
Outlet 3 (on)
Outlet 4
(off)
Outlet 4 (on)
Outlet 1
(off)
Outlet 1 (on)
Outlet 2
(off)
Outlet 2 (on)
Outlet 3
(off)
Outlet 3 (on)
Outlet 4
(off)
Outlet 4 (on)
Outlet 1
(off)
Outlet 1 (on)
Outlet 2
(off)
Outlet 2 (on)
Outlet 3
(off)
Outlet 3 (on)
Outlet 4
(off)
Outlet 4 (on)
Outlet 1
(off)
Outlet 1 (on)
Outlet 2
(off)
Outlet 2 (on)
Outlet 3
(off)
Outlet 3 (on)
Outlet 4
(off)
Outlet 4 (on)
Outlet 1
(off)
0x29
0x2A
Thursday
Thursday
0x2B
0x2C
Thursday
Thursday
0x2D
0x2E
Thursday
Thursday
0x2F
0x30
Thursday
Friday
0x31
0x32
Friday
Friday
0x33
0x34
Friday
Friday
0x35
0x36
Friday
Friday
0x37
0x38
Friday
Saturday
0x39
0x3A
Saturday
Saturday
0x3B
0x3C
Saturday
Saturday
0x3D
0x3E
Saturday
Saturday
0x3F
Saturday
Outlet 1 (on)
Outlet 2
(off)
Outlet 2 (on)
Outlet 3
(off)
Outlet 3 (on)
Outlet 4
(off)
Outlet 4 (on)
Outlet 1
(off)
Outlet 1 (on)
Outlet 2
(off)
Outlet 2 (on)
Outlet 3
(off)
Outlet 3 (on)
Outlet 4
(off)
Outlet 4 (on)
Outlet 1
(off)
Outlet 1 (on)
Outlet 2
(off)
Outlet 2 (on)
Outlet 3
(off)
Outlet 3 (on)
Outlet 4
(off)
Outlet 4 (on)
This makes the organization much cleaner, since each day of the week is organized into a
nice 8 bytes, versus the less natural 14 bytes when organized by outlet number. This simplified
the source code significantly as well. Both the setting and the checking of the programmed times
is done relative to a day of the week. Therefore, if just the starting addresses of each day of the
week is defined at the top of the source code, it is easy to use a derived offset to quickly lookup
any outlet for any day of the week. This offset is defined as: (outletNumber - 1) * 2. For
example, outlet 1 needs no offset since its 2 bytes are stored at the starting address for each day
of the week. Outlet 3, however, is stored (3 – 1)*2 = 4 bytes lower than outlet 1. This offset is
simply added to the initial address for any day of the week in order to get the address for a
different outlet for that day of the week. This simplifies the code into for-loops and switch
statements for getting and setting programmed times stored in the RTC’s RAM.
User Interface & LCD Menus
The DuraSaver features a 2-line 24-character LCD, four directional buttons, and one
select button with which the user interacts to program and use their power controller. When in
‘idle’ mode – meaning that the power controller is handling programmed on/off times and
managing the outlet’s on/off status accordingly – the LCD displays the time and date (see Figure
1). The user can press any of the four directional buttons to navigate away from this idle screen
and traverse the other menus. From the idle screen, the user can press LEFT to get to the
programming menu for the outlets; RIGHT to get to the programming menu for the clock; UP to
turn on manual override for each of the outlets; DOWN to turn off manual override for each of
the outlets. Below is a state-machine diagram of the main LCD menu interface:
Once in the outlet programming menu, the user can either choose an outlet to program (or
view programmed times for) or choose to exit back to the main LCD menu. After choosing an
outlet, the user can either choose a day of the week or choose to exit back to the outlet selection.
After choosing a day of the week, the user can view or change the turn-off and turn-on times for
the chosen outlet and day, and the LCD menu returns to the day selection: turn-off hour turn-
off minute turn-on hour turn-on minute day of the week. There is no way to exit from
this stream without viewing all four, but the user can just press RIGHT four times to get back to
the day selection screen. Additionally, the user can press LEFT or RIGHT to pan through and
simply view these times without changing them, or change them but choose not to save the
changes; only by pressing SELECT are the altered times saved back to the RTC for
implementation. On the current prototype, the menus only function in one direction; a future
improvement would be to make the menus more bi-directional so that pressing RIGHT would
advance to the next menu (as above) but LEFT would go back. UP and DOWN scroll through
the various options on the current LCD menu screen, while the LCD updates the current
selection in real-time. The turn-on/turn-off hours are displayed in 12-hour format with AM/PM.
The hours are displayed with the turn-on/turn-off minutes in case the user forgets what was
saved in the previous menu, though only the minutes are alterable in that menu. Again, the
minutes are in 10-minute intervals.
The clock and date programming menu is very similar to the outlet programming menu
with a few differences. First, there are no intermediate selections like outlet or day from which
the user can exit; once inside this menu, the user must pan through each of them before returning
to the main LCD menu. Again, an ideal future improvement would be ‘back’ functionality of the
LEFT button. However, it is pure convenience, as the user merely must press RIGHT a few
times to get back to the main menu: Day of the Week Month Date Year Hour (12hour, am/pm format) Minute Main Menu (display the time and date). Similar to the outlet
programming menu, UP and DOWN scroll through the options for each of these screens with the
LCD updating in real-time, SELECT saves them, and RIGHT cancels/moves on to the next
screen.
The manual override menus are very simple. UP and DOWN scroll among the outlets
and “exit”, while SELECT acts on the current selection. For the “manual override on” menu,
when an outlet is selected, its manual override is turned (or kept) on and its ‘on’ state is toggled –
if the outlet is on, it is turned off, and vice versa. This is immediately implemented while still in
the “manual override on” menu. In contrast, for the “manual override off” menu, the manual
override for the chosen outlet is turned off and the outlet’s ‘on’ state is defaulted back to the
programmed times. This effect is only visible after exiting the “manual override off” menu, as
the rest of the “check on/off times” program must be executed. As expected, if “exit” is chosen
in either of these menus, the LCD screen returns to the main idle menu.
In addition to the hardware debouncing of the buttons, we implemented simple software
debouncing of the buttons as well. When a button is pressed, the software waits for the button to
be released before moving on. This could be improved but storing a state of each button
(waiting, pressed down, and released) so that the software continues to execute while it waits for
a pressed-button to be released; however, because of the simplicity of our program, this simpler
debouncing works efficiently. Additionally, because of how the program is structured, only 1
button press is acknowledged at a time. Even if a user pressed both RIGHT and LEFT at the
same time, a hierarchy chooses which one is acted upon. The only hazard is that the second
button could be acted upon later in a different context based on the timing of its release relative
to the first button. For example, if RIGHT were pressed and held and then LEFT were pressed
and held before releasing RIGHT, the program would wait for RIGHT to be released regardless
of whether or not LEFT is released before, simultaneously, or after. However, if LEFT is held
down long enough after RIGHT is released, and the following menu looks for a LEFT button
press, LEFT will be acted on once it is released. Again, storing a state for each button could
prevent this by keeping track of if the LEFT button was pressed down before or after the
program starts checking for LEFT. This is a “dummy-proofing” mechanism that was not
necessary for our prototype but which would be important to implement in future builds.
The Main Program
The main loop that executes infinitely checks for a list of things. First, it checks if any
buttons have been pressed – LEFT for programming outlets menu, RIGHT for programming
clock menu, UP for turning on manual override, DOWN for turning off manual override. If no
buttons are being pressed, it checks if the RF remote is requesting manual override. Last, it does
a check for each outlet to see if it needs to be turned on or off. For an outlet to be turned on,
manual override must be off and the outlet must be off; for an outlet to be turned off, manual
override must be on and the outlet must be on. Additionally, “check_ontime(outlet)” and
“check_offtime(outlet)” subroutines are called, which return true if an action (either turning an
outlet on, or turning and outlet off, respectively) can be taken. Each of these subroutines that
check if an outlet needs to be turned on or off look at 3 cases:
(1) Always On: Turn-on time = Turn-off time
(2) Usually On: Turn-on time > Turn-off time
(3) Usually Off: Turn-on time < Turn-off time
Since outlets are on by default, the first case means that an outlet is never turned off. The
second case is “usually on”, meaning the outlet is on except for the programmed window of time
when it is off. Conversely, the third case is “usually off”, meaning that the outlet is off except
for the programmed window of time when it is on.
In the check for turn-off time, if case (2) is true and the time now is inside of the “off”
window (time-now > time-off and time-now < time-on), then check_offtime returns true. If case
(3) is true and the time now is outside of the “on” window (time-now < time-on or time-now >
time-off), then check_offtime returns true. In all other cases, check_offtime returns false,
meaning that the outlets do not need to be turned off. The check for turn-on time works
similarly. If case (2) is true, it checks if the time now is outside of the “on” window, and if case
(3) is true, it checks if the time now is inside of the “on” window.
It seems at first glance as though this wastes a lot of cycles on checking, but these check
on/off time subroutines are only called if the outlet is currently in the opposite state (e.g.
check_ontime is only called if the outlet is currently off). It is still constantly checking, but only
for valid things to check (e.g. if the outlet is on, the program does not check if the outlet needs to
be turned on, because that is an invalid thing to check).
In order to simplify the code to check if time-on > time-off, etceteras, we implemented a
“qualifyTime” method. This transforms any time into a whole integer value that can be
compared with other times. It does this by giving the 10’s hour a weight of 1000, the 1’s hour a
weight of 100, the 10’s minute a weight of 10, and the 1’s minute a weight of 1. The AM/PM
value adds 1200 to the time to convert from 12-hour to 24-hour format when qualifying time.
Below is a visual representation of the value qualify-time returns; each box represents a digit in
the integer returned:
10’s Hour 1’s Hour 10’s Minute 1’s Minute
This method is called for time-now, time-on, and time-off so they can be easily compared
to one another multiple times without messy if-else statements. It modularizes the code to make
it cleaner and easier to understand, as well as more efficient since qualifyTime only needs to be
called once at the beginning of each check on/off time method call while the values it returns are
used multiple times within the method.
Section III: System Integration & Testing
Before testing the software itself, the hardware – especially in connection to the
microcontroller – needed to be tested. This was done from low-level to high-level.
First we tested the microcontroller’s pins as outputs by toggling an output put on and off
and reading it on an LED. Second we tested the microcontroller’s pins as inputs by pressing a
button and outputting to the LED when a button is pressed. Third we tested multiple buttons as
inputs by blinking the LED a different number of times based on which button was pressed.
Once we verified this basic functionality, we moved on to testing higher level components.
Since most of the system functionality and debugging is verified via the LCD, we tested
that next. First we tried printing something static to each line of the LCD, and when that
worked, we added interaction with the buttons to print out which button was pressed. Once we
verified the LCD response to code, we tested and debugged the LCD menus – do they flow as
expected? Do values increment, decrement, and cycle around from min to max and max to min
all as expected?
A clearLCD () method was also added to clear the LCD display in between prints, if
necessary, so that extra characters are not left over in the case where the previous print statement
is longer than the next one. Methods to clear each of the 2 lines independently were also coded,
but never used.
Lastly, before implementing and testing the main routine, we tested writing to and
reading from the Real Time Clock on the I2C bus. From there we tested the format for storing
time and date, followed by manipulation of those values. Once we could successfully set and
save the current date and time, we verified battery back-up. From there, we tested writing to and
reading from the various locations of the RTC RAM – are the start addresses for each day of the
week correct? Does the offset work as it is supposed to?
Once all the basic components were tested and verified as working individually, we
tested our main loop to verify that outlets turned on and off when expected based on the
programmed time, date, and on/off times. We used LEDs to represent the outlets until we had
relays on the board. Once we had relays and outputs to a test board, we verified that we could
turn on and off the outlets at will, then tested our main program.
When all the main functionality was working, we added in manual override. In case we
could not get the RF remote to work, we implemented it using buttons directly on the board.
This seemed important in order to make our product reliable. This proved true because our RF
remote did not communicate button presses 100% of the time, and we ran out of time to fix this
issue before the prototype deadline. However, we did successfully test the remote toggling
outlets on and off external to the main program, and this worked at least part of the time. A
future improvement would be to make this reliable all the time – by finding and solving the
cause of the synchronization failing between RF sender and receiver – and then integrating it into
the main program.
Section IV: Obstacles
Software Struggles
In addition to all of the regular and expected challenges of integrating and testing
software and hardware in a system, we had two major hurdles that significantly impeded our
progress throughout the project.
Initially, we were not aware of the extremely limited amount of memory dedicated to the
stack, and this caused us to spend a lot of time searching in the wrong places for the source of
strange program behavior. Upon learning that other groups had strange behavior caused by
overflowing from their stack space, the solution was simple – make the 24-character test string a
global variable instead of a local one used in several subroutines. Had we made note of the 50byte stack space in the beginning, we could have very easily avoided this issue.
Secondly, our LCD caused us a lot of headaches throughout the semester. In order to cut
costs, we ordered a pre-used LCD; it was only 10% of the cost of similar new items, but as we
found, it made it temperamental. For the most part, the LCD did what we expected, but on
random occasions would print garbage or freeze, even though nothing in the source code had
changed. Every once in a while, it would refuse to turn on at all. At first we thought that we
might be sending characters to the LCD too quickly and tried adding in delays, but the routine
that sends characters one at a time to the LCD checks the busy flag, so that would not have been
an issue. It is possible that when we were testing it out and initially hooked it up backwards that
something was burnt out. We did not conclude this until the very end, so if we had more time we
could have tried swapping our LCD out for another, which may have solved the garbage and
refresh issues instantly.
Section V: Future Improvements
Software Improvements
In addition to the improvements already stated that would improve efficiency, reliability,
and “dummy proofing” of our prototype, there are several features that could be added to future
releases that would improve our product.
The most obvious improvement is the ability to store more than just 2 programmable time
for each day. This would mean adding an EPROM, since our RTC RAM is completely full with
our current configuration. Doing this would also make it possible to program times independent
of each other. For example, right now we have the user select an outlet and then a day, and from
there they program one off time and one on time. The improvement would be to have the user
select an outlet, select a day, and then select which action they want associated with the time
they are setting (on, or off) such that the outlet can be turned off one day and turned on again on
a completely separate day. This would also mean that an outlet could be turned off and on again
multiple times in the same day, subject to the limits of EPROM space that we add.
Hardware Improvements
Though we already have two different methods of manual override – setting with buttons
interfaced with the microcontroller, and toggling with the RF remote – it would be good to add a
physical switch to implement manual override independent of the microcontroller in case it is
malfunctioning. A 3-position switch would be best for 3 settings: manual override everything
‘on’, manual override everything ‘off’, and autopilot such that the microcontroller takes over the
outlets’ on/off status. This would make it possible to override the whole system and hard-set the
outlets on or off; it would act like a regular power strip when activated.
Figure 1: LCD Idle Screen displays the current time and date
One possible future hardware improvement was alluded to in the above discussions of the
315MHz RF link circuit modules. As discussed, we found the signal strength between the
transmitter and receiver to be unreliable and in serious need of improvement. One way that this
signal strength could be improved would be to run the transmitter at a higher source voltage. The
following annotated diagram is an extract from the RF transmitter’s datasheet:
As can be seen, this transmitter can be run at anywhere from 1.5 to 12 V. Since 5V was well
within the specified “typical” supply voltage, we initially used a normal TTL 5V supply line to
power the transmitter. Upon finding such a weak signal strength, we moved the supply line of the
transmitter on our prototype board from the 5V regulator output to the 9V battery output.
However, it was not possible to change the printed-circuit board transmitter supply voltage, since
the signal traces are printed immovably onto the board. We were able to observe a very
noticeable difference in signal strengths between the two remote control boards running the
transmitters at the two different aforementioned supply voltages. While the prototype board
typically worked up to a couple meters away from the receiver (still disappointing for RF
equipment), the PCB transmitter had to be placed within a centimeter or so of the receiver board
in order to get a reasonable transmission. Since the supply voltage seems to have such a drastic
effect on signal strength, a future implementation of this project could use a 9V-to-12V “boost”
converter to supply the transmitter voltage. In addition, signal strength could be further improved
by connecting 315MHz antennas to both receiver and transmitter chips.
Another improvement that could be made to the hardware would be to use more robust
relays in order to solve the current loading problems detailed in the above “Outlet Outputs”
heading of the “Main Module” section of this report. This would eliminate the need for the highpower resistors on our main module board (enabling a lower component count and a smaller
footprint), and would also allow more realistic AC current loads that would better mirror real-life
current loading situations.
Conclusion
In conclusion, the ultimate goal of this project was achieved. We were able to construct a device
that can successfully “unplug” devices according to times programmed by the user. As expected,
the user can simply program the times on the device or use the remote control (when working
efficiently) to manually override the programmed times. Even though the final design was very
sound, there are always ways that any type of device can be improved in hindsight after taking a
step back and taking a look at the project as a whole.
Appendix A
Schematics
C:\Documents and Settings\Paul VanWieren\Desktop\My Dropbox\EE459\EE 459L Project Schematics\EE 459L Project Schematic.sch - Main uC Interface
C:\Documents and Settings\Paul VanWieren\Desktop\My Dropbox\EE459\EE 459L Project Schematics\EE 459L Project Schematic.sch - Switch Interface
C:\Documents and Settings\Paul VanWieren\Desktop\My Dropbox\EE459\EE 459L Project Schematics\EE 459L Project Schematic.sch - LCD Interface
C:\Documents and Settings\Paul VanWieren\Desktop\My Dropbox\EE459\EE 459L Project Schematics\EE 459L Project Schematic.sch - Timing Interface
C:\Documents and Settings\Paul VanWieren\Desktop\My Dropbox\EE459\EE 459L Project Schematics\EE 459L Project Schematic.sch - Outlet Interface
C:\Documents and Settings\Paul VanWieren\Desktop\My Dropbox\EE459\EE 459L Project Schematics\EE 459L Project Schematic.sch - Remote Control
Appendix B
Source Code
Appendix B: Source Code
Source Code for Main Module
/*********************************************************************
* EE 459 Spring 2009 Team 1 - Duracell
* Sara Adkins
* Paul VanWieren
* Robert Whitley
*********************************************************************/
#include <stdio.h>
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include <string.h>
/* The following puts the dummy interrupt service routine at
location MY_ISR_ROM which is defined in the PRM file as
the start of the FLASH ROM */
#pragma CODE_SEG MY_ISR_ROM
#pragma TRAP_PROC
void dummyISR(void) { }
/* This prag sets the code storage back to default area of ROM
as defined in the PRM file */
#pragma CODE_SEG DEFAULT
/*
*
Port D, bit 1 (0x02) - output to RS (Register Select) input of display
*
bit 2 (0x04) - output to R/W (Read/Write) input of display
*
bit 3 (0x08) - output to E (Enable) input of display
*
Port B, bits 4-7 - Outputs to DB4-DB7 inputs of display.
*
*
The second line of the display starts at address 0x40.
*
* ---Storage of On/Off times on RTC:--* Bits 7-4: Hour (1-12)
* Bits 3-1: Minute (0-5, x10)
* Bit 0: AM/PM
* x2 times per device x7 days x4 devices = 56 bytes (total RAM!)
*
void LCDMenu(void);
void mainLoop(void);
void dummyMain(void);
//TEST//
void testOutlets(void);
void fakeLCD(void);
void testButtonsLED(void);
void testButtonsLCD(void);
void testI2Crap(void);
void testCLKRegs(void);
void testOutlets(void);
void testRemote(void);
//TEST//
/* button input ports */
#define LEFT PTA_PTA1
#define RIGHT PTD_PTD6
#define UP PTD_PTD5
#define DOWN PTD_PTD4
#define SELECT PTD_PTD0
* Device 1: reg 0x08 - 0x15
* Device 2: reg 0x16 - 0x23
* Device 3: reg 0x24 - 0x31
* Device 4: reg 0x32 - 0x3F
*/
/* The NIBBLE_HIGH condition determines whether PTB bits 4-7 or 0-3 are used
to send the four bit nibble to the LCD.
If NIBBLE_HIGH is declared, use PTB 4-7.
If NIBBLE_HIGH not declared, use PTB 0-3. */
#define NIBBLE_HIGH // Use bits 4-7 for talking to LCD
/* function declarations */
void initializeLCD(void);
void clearLCD(void);
void strout(int, unsigned char *);
void iniout(unsigned char);
void cmdout(unsigned char);
void datout(unsigned char);
void nibout(unsigned char);
void busywt(void);
void del40u(int);
void del1m(int);
void sci_init(void);
void i2c_init(unsigned char);
void i2c_write2(unsigned char, unsigned char *, int, unsigned char);
void i2c_read2(unsigned char, unsigned char *, int, unsigned char);
void clk_init(void);
void clkRAM_init(void);
void clkRegs_init(void);
void blink(int);
void manualOn(void);
void manualOff(void);
unsigned char checkManualOverride(void);
unsigned char check_offtime(unsigned char);
unsigned char check_ontime(unsigned char);
unsigned int qualifyTime(unsigned char, unsigned char);
void testCLK(void);
void getTime(void);
void getDevData(unsigned char);
void programCLK(void);
void programOutlet(unsigned char);
void programDEV(void);
void progMenuTime(void);
void progMenuOutlets(void);
void LCD_Time(void);
#define TUEREG 24
#define WEDREG 32
#define THUREG 40
#define FRIREG 48
#define SATREG 56
#define TOTALDEVS 4 //4 devices/outlets total
/* This pragma sets the area for allocating variables to the zero page
of RAM (0x00 to 0xff) for more efficient access.*/
#pragma DATA_SEG __SHORT_SEG MY_ZEROPAGE
unsigned char delay0;
unsigned char delay1;
unsigned char delay2;
/* This pragma sets the area for allocating variables back to the default area
of RAM as defined in the PRM file. */
#pragma DATA_SEG DEFAULT
/* outlet output ports */
#define OUTLET1 PTB_PTB0
#define OUTLET2 PTB_PTB1
#define OUTLET3 PTB_PTB2
#define OUTLET4 PTB_PTB3
/* LCD */
#define LCD_LINE1 0
#define LCD_LINE2 0x40
/* Addresses for the clock on the I2C bus */
#define CLOCK_WR_ADDR 0xD0 /* clock write address */
#define CLOCK_RD_ADDR 0xD1 /* clock read address */
/* clk reg organized by day of the week */
#define SUNSTART 0x08 //for i2c read/write
#define MONSTART 0x10
#define TUESTART 0x18
#define WEDSTART 0x20
#define THUSTART 0x28
#define FRISTART 0x30
#define SATSTART 0x38
#define SUNREG 8 //for clkRegs[]
#define MONREG 16
/* Declare these strings as "const" so they are allocated in ROM */
//TEST//
#ifdef NIBBLE_HIGH
const unsigned char str1[] = "Hi! Press a button";
#else
const unsigned char str1[] = "'lo! Press a button";
#endif
const unsigned char str2[] = "...if you DARE";
const unsigned char str3[] = "Dare to press another?";
const unsigned char upstr[] = "you pressed UP!";
const unsigned char downstr[] = "you pressed DOWN!";
const unsigned char leftstr[] = "you pressed LEFT!";
const unsigned char rightstr[] = "you pressed RIGHT!";
const unsigned char selectstr[] = "you pressed SELECT!";
//TEST//
const unsigned char clearstr[] = "
";
const unsigned char strdurasaver[] = "Duracell DuraSaver
";
const unsigned char strprogmenu[] = "Programming Menu";
const unsigned char strprogdev[] = "Program Devices";
const unsigned char strsetclk[] = "Set Clock & Date";
const unsigned char strexit[] = "Exit ";
const unsigned char stroutlet[] = "Select Outlet";
const unsigned char strprogday[] = "Select Day of the Week";
const unsigned char stroffhour[] = "Select Off Hour";
const unsigned char stroffmin[] = "Select Off Minute";
const unsigned char stronhour[] = "Select On Hour";
const unsigned char stronmin[] = "Select On Minute";
const unsigned char strweekday[] = "Set Day of the Week";
const unsigned char strsun[] = "Sunday ";
const unsigned char strmon[] = "Monday ";
const unsigned char strtue[] = "Tuesday ";
const unsigned char strwed[] = "Wednesday";
const unsigned char strthu[] = "Thursday ";
const unsigned char strfri[] = "Friday ";
const unsigned char strsat[] = "Saturday ";
const unsigned char strmonth[] = "Set Month";
const unsigned char strjan[] = "January ";
const unsigned char strfeb[] = "February ";
const unsigned char strmar[] = "March ";
const unsigned char strapr[] = "April ";
const unsigned char strmay[] = "May ";
const unsigned char strjun[] = "June ";
const unsigned char strjul[] = "July ";
const unsigned char straug[] = "August ";
const unsigned char strsep[] = "September";
const unsigned char stroct[] = "October ";
const unsigned char strnov[] = "November ";
const unsigned char strdec[] = "December ";
const unsigned char strdate[] = "Set Date (01-31)";
const unsigned char stryear[] = "Set Year (2000-2099)";
const unsigned char strtimehr[] = "Set Hour (01-12 AM/PM)";
const unsigned char strtimemin[] = "Set Minute (00-59)";
const unsigned char strmanon[] = "Manual Override On";
const unsigned char strmanoff[] = "Manual Override Off";
const unsigned char strohnoes[] = "???";
const unsigned char hexCode[] = "0123456789ABCDEF";
const unsigned char one = 1;
const unsigned char zero = 0;
const unsigned int thousand = 1000;
const unsigned char keeppw = 0xF0;
const unsigned char keepcode = 0x0F;
const unsigned char password = 0xD0;
const unsigned char code0 = 0x00;
const unsigned char code1 = 0x01;
const unsigned char code2 = 0x02;
const unsigned char code3 = 0x03;
/* global variables */
const unsigned char swDebounce = 1; //1 for software debounce, 0 for hardware only
unsigned char PWCODE;
unsigned char PW;
unsigned char CODE;
unsigned char today; //this is for LCD menu; actual current day of the week is stored in
dayofweek (against all common sense, I know)
unsigned char timesToday; //keeps track of which day of the week's on/off times are stored in the
off/on[] variables
unsigned char seconds10, seconds09, minutes10, minutes09, hours10, hours09, pm,
dayofweek, date10, date09, months10, months09, years10, years09; //time right now get from clock
unsigned char off10hr[TOTALDEVS], off09hr[TOTALDEVS], offmin[TOTALDEVS],
offpm[TOTALDEVS], //programmed "off" times, 1 per each of 4 devices
on10hr[TOTALDEVS], on09hr[TOTALDEVS], onmin[TOTALDEVS],
onpm[TOTALDEVS];
//programmed "on" times, 1 per each of 4 devices
/* manual override - 0 is off, 1 is on (default is off) */
unsigned char manual[TOTALDEVS];
/* outlets - 0 is off, 1 is on (default is on) */
unsigned char outlet[TOTALDEVS];
unsigned char time[24]; //Day, MO/DD/YR HH:MM xm
unsigned char teststr[24]; //to print test statements, variables
unsigned char clkRegs[64];
unsigned char dayData[8];
/****************** MAIN ******************/
void main(void) {
// EnableInterrupts; /* enable interrupts */
/* include your code here */
CONFIG1_COPD = 1;
CONFIG2_IICSEL = 1;
// disable COP reset
// IIC on PTA2, 3
DDRA_DDRA0 = 1;
DDRD_DDRD0 = 0;
DDRD_DDRD4 = 0;
DDRD_DDRD5 = 0;
DDRD_DDRD6 = 0;
DDRA_DDRA1 = 0;
// Set PTA0 = 1 for output (LED)
// clear PTD0 = 0 for input (SELECT button)
// clear PTD4 = 0 for input (DOWN button)
// clear PTD5 = 0 for input (UP button)
// clear PTD6 = 0 for input (RIGHT button)
// clear PTA1 = 0 for input (LEFT button)
PTA_PTA0 = 1;
/* Set baud rate to 38,400. Clock = 9.8304MHz. Divisor = 64. */
i2c_init((unsigned char) 3); // Initialize the IIC port
sci_init();
// Initialize the SCI port
#ifdef NIBBLE_HIGH
DDRB = 0xf0;
#else
DDRB = 0x0f;
#endif
DDRD = 0x0e;
// Set PTB bits 4-7 for output
/********************************************* MAIN LCD MENU
*********************************************/
void dummyMain() {
del1m(thousand);
clearLCD();
del1m(thousand);
mainLoop();
}
// Set PTB bits 0-3 for output
// Set PTD1, 2, and 3 for output
initializeLCD();
// Initialize the LCD display
//ONLY ONCE//clk_init(); // Initialize the Clock (ONLY HAS TO BE DONE ONCE)
//clkRAM_init(); //initialize the clkRegs + initalize the clock RAM (other than time & date)
clkRegs_init(); //initialize the clkRegs
del1m(thousand);
DDRB_DDRB0 = 1;
// Set PTB0 = 1 for output (Outlet 1)
DDRB_DDRB1 = 1;
// Set PTB1 = 1 for output (Outlet 2)
DDRB_DDRB2 = 1;
// Set PTB2 = 1 for output (Outlet 3)
DDRB_DDRB3 = 1;
// Set PTB3 = 1 for output (Outlet 4)
outlet[0] = 1;
OUTLET1 = 1; //Outlet 1 on by default
outlet[1] = 1;
OUTLET2 = 1; //Outlet 2 on by default
outlet[2] = 1;
OUTLET3 = 1; //Outlet 3 on by default
outlet[3] = 1;
OUTLET4 = 1; //Outlet 4 on by default
del1m(thousand);
timesToday = dayofweek;
/* main loop */
while(one) {
dummyMain();
}
/* please make sure that you never leave this function */
}
//LED off
void mainLoop() {
unsigned char outletNum = TOTALDEVS;
strout(LCD_LINE1, (unsigned char *) strdurasaver);
testCLK();
while(one) {
del1m(thousand);
clearLCD();
getTime(); //update time variables
// check for RIGHT button press --> program clock
if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
progMenuTime();
}
// check for LEFT button press --> program outlets
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
progMenuOutlets();
}
//check for UP button press --> turn on manual override
else if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
manualOn();
}
//check for DOWN button press --> turn off manual override
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
manualOff();
}
} //end if manual override currently off
// check for manual override (on --> off)
else if(manual[outletNum-1] == 1) {
manual[outletNum-1] = 0;
} //end if manual override currently on
for(outletNum = TOTALDEVS; outletNum > 0; outletNum--) { //for each device
// check for RF remote manual override request
if(checkManualOverride() == outletNum) {
// check for manual override (off --> on)
if(manual[outletNum-1] == 0) { //if manual override currently off
manual[outletNum-1] = 1;
if(outlet[outletNum-1] == 1) { //outlet 1 is on --> turn it off
outlet[outletNum-1] = 0;
switch(outletNum) {
case 1:
OUTLET1 = 0;
break;
case 2:
OUTLET2 = 0;
break;
case 3:
OUTLET3 = 0;
break;
case 4:
OUTLET4 = 0;
break;
} //end switch
//strout(LCD_LINE1, "manv off!");
//del1m(thousand);
}
else { //outlet 1 is off --> turn it on
outlet[outletNum-1] = 1;
switch(outletNum) {
case 1:
OUTLET1 = 1;
break;
case 2:
OUTLET2 = 1;
break;
case 3:
OUTLET3 = 1;
break;
case 4:
OUTLET4 = 1;
break;
} //end switch
//strout(LCD_LINE1, "manv on !");
//del1m(thousand);
}
case 3:
OUTLET3 = 1; //on
break;
case 4:
OUTLET4 = 1; //on
break;
} //end switch
//strout(LCD_LINE1, "time on !");
//del1m(thousand);
}
}
}
else { //idle --> display time and date
//testCLK();
LCD_Time();
} //end idle
} //end for each device
} //end while(one)
}
void LCD_Time() {
//getTime();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strdurasaver);
del1m(2);
testCLK();
//del1m(500);
}
void manualOn() {
unsigned char choice = 0; //0 = exit
unsigned char repeat = 1;
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
while(repeat) {
switch(choice) {
case 0:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) strexit);
}
// check if need to turn off outlet
if(outlet[outletNum-1] == 1) {
if(manual[outletNum-1] == 0) {
if(check_offtime(outletNum) == 1) {
outlet[outletNum-1] = 0;
//OUTLET1 = 0; //OFF
switch(outletNum) {
case 1:
OUTLET1 = 0; //off
break;
case 2:
OUTLET2 = 0; //off
break;
case 3:
OUTLET3 = 0; //off
break;
case 4:
OUTLET4 = 0; //off
break;
} //end switch
//strout(LCD_LINE1, "time off!");
//del1m(thousand);
}
}
}
// check if need to turn on outlet
else if(outlet[outletNum-1] == 0) {
if(manual[outletNum-1] == 0) {
if(check_ontime(outletNum) == 1) {
outlet[outletNum-1] = 1;
//OUTLET1 = 1; //ON
switch(outletNum) {
case 1:
OUTLET1 = 1; //on
break;
case 2:
OUTLET2 = 1; //on
break;
break;
case 1:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 1");
break;
case 2:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 2");
break;
case 3:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 3");
break;
case 4:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 4");
break;
default:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet ?");
break;
} //end switch
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
//choice = (choice + 1) % 5;
if(choice == 4)
choice = 0;
else
choice++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
//choice = (choice - 1) % 5;
if(choice == 0)
choice = 4;
else
choice--;
} //end if DOWN
//del1m(thousand);
} //end if outlet off --> on
strout(LCD_LINE2, "confirmed - another?");
del1m(500);
clearLCD();
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
}//end if choice != 0
if(choice != 0) {
manual[choice - 1] = 1; //turn on manual override
if(outlet[choice - 1] == 1) { //outlet is on --> turn it off
outlet[choice - 1] = 0;
switch(choice) {
case 1:
OUTLET1 = 0; //OFF
break;
case 2:
OUTLET2 = 0; //OFF
break;
case 3:
OUTLET3 = 0; //OFF
break;
case 4:
OUTLET4 = 0; //OFF
break;
} //end switch
//strout(LCD_LINE1, "manv off!");
//del1m(thousand);
} //end if outlet is on --> off
else if(outlet[choice - 1] == 0) { //outlet is off --> turn it on
outlet[choice - 1] = 1;
switch(choice) {
case 1:
OUTLET1 = 1; //ON
break;
case 2:
OUTLET2 = 1; //ON
break;
case 3:
OUTLET3 = 1; //ON
break;
case 4:
OUTLET4 = 1; //ON
break;
} //end switch
//strout(LCD_LINE1, "manv on !");
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 3");
break;
case 4:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 4");
break;
default:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet ?");
break;
} //end switch
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
//choice = (choice + 1) % 5;
if(choice == 4)
choice = 0;
else
choice++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
//choice = (choice - 1) % 5;
if(choice == 0)
choice = 4;
else
choice--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
if(choice != 0) {
manual[choice - 1] = 0; //turn on manual override
strout(LCD_LINE2, "confirmed - another?");
del1m(500);
clearLCD();
}//end if choice != 0
else if(choice == 0) {
repeat = '0';
break;
}
} //end if SELECT
} //end repeat
}
void manualOff() {
unsigned char choice = 0; //0 = exit
unsigned char repeat = 1;
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
while(repeat) {
switch(choice) {
case 0:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) strexit);
break;
case 1:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 1");
break;
case 2:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 2");
break;
case 3:
else if(choice == 0) {
repeat = '0';
break;
}
} //end if SELECT
} //end repeat
}
unsigned int qualifyTime(unsigned char outletNum, unsigned char ontime) {
unsigned int qualval, q10hr, q09hr, q10min, q09min, qpm;
getTime(); //update time variables
getDevData(dayofweek); //update on/off times for current day
if(outletNum == 0) { //NOW
q10hr = hours10 & 0x01;
q09hr = hours09 & 0x0f;
q10min = minutes10 & 0x07;
q09min = minutes09 & 0x0f;
qpm = pm & 0x01;
}
else if((outletNum != 0) && (ontime == 1)) {
q10hr = on10hr[outletNum-1] & 0x01;
q09hr = on09hr[outletNum-1] & 0x0f;
q10min = onmin[outletNum-1] & 0x07;
q09min = 0;
qpm = onpm[outletNum-1] & 0x01;
}
else {
q10hr = off10hr[outletNum-1] & 0x01;
q09hr = off09hr[outletNum-1] & 0x0f;
q10min = offmin[outletNum-1] & 0x07;
q09min = 0;
qpm = offpm[outletNum-1] & 0x01;
}
if((q10hr == 1) && (q09hr == 2)) { //12xm is always < anything else xm
//qualval = (q10hr * 0) + (q09hr * 0) + (q10min * 10) + (q09min * 1) + (qpm * 1200);
qualval = (q10min * 10) + (q09min) + (qpm * 1200);
}
else {
//qualval = (q10hr * 1000) + (q09hr * 100) + (q10min * 10) + (q09min * 1) + (qpm * 1200);
qualval = (q10hr * 1000) + (q09hr * 100) + (q10min * 10) + (q09min) + (qpm * 1200);
}
return qualval;
}
qNOW = qualifyTime(0, 1);
if(qON == qOFF) { //off and on times are the same --> default ON
//strout(LCD_LINE1, "qON == qOFF");
//del1m(thousand);
return 1;
}
/* Check Off Time
* This function checks if the given outlet
* is scheduled to be off right now
*/
unsigned char check_offtime(unsigned char outletNum){
unsigned int qON, qOFF, qNOW;
qON = qualifyTime(outletNum, 1);
qOFF = qualifyTime(outletNum, 0);
qNOW = qualifyTime(0, 1);
if(qOFF < qON) { //turn off then turn on (usually on)
if((qNOW < qOFF) || (qNOW >= qON)) { //time now is before off-time or after on-time
//strout(LCD_LINE1, "outside off-time");
//del1m(thousand);
return 1;
}
}
if(qON == qOFF) { //off and on times are the same --> default ON
//strout(LCD_LINE1, "qOFF == qON");
//del1m(thousand);
return 0;
}
if(qOFF < qON) { //turn off then turn on (usually on)
if((qNOW >= qOFF) && (qNOW < qON)) { //time now is after off-time but before on-time
//strout(LCD_LINE1, "btwn off & on");
//del1m(thousand);
return 1;
}
}
if(qON < qOFF) { //turn on then turn off (usually off)
if((qNOW < qON) || (qNOW >= qOFF)) { //time now is before on-time or after off-time
//strout(LCD_LINE1, "outside on-time");
//del1m(thousand);
return 1;
}
}
return 0;
}
/* Check On Time
* This function checks if the given outlet
* is scheduled to be on right now
*/
unsigned char check_ontime(unsigned char outletNum){
unsigned int qON, qOFF, qNOW;
qON = qualifyTime(outletNum, 1);
qOFF = qualifyTime(outletNum, 0);
if(qON < qOFF) { //turn on then turn off (usually off)
if((qNOW >= qON) && (qNOW < qOFF)) { //time now is after on-time but before off-time
//strout(LCD_LINE1, "btwn off and on");
//del1m(thousand);
return 1;
}
}
return '0';
}
/* Check for Manual Override
* Returns Outlet Number of Outlet Toggling Manual Override
* Returns 0 if no Outlet is requesting manual override
*/
unsigned char checkManualOverride() {
if(SCS1_SCRF) { //check flag
PWCODE = SCDR;
PW = PWCODE&keeppw;
if(PW == password) {
CODE = PWCODE&keepcode;
if(CODE == code0) {
return 1;
} //end if for code0 check
else if(CODE == code1) {
return 2;
} //end elseif for code1 check
else if(CODE == code2) {
return 3;
} //end else if for code1 check
else if(CODE == code3) {
return 4;
} //end else if for code3 check
else {
return 0;
}//do nothing if code is not valid
} //end if for password checking
else {
return 0;
} //do nothing if password is not correct
} //end if for serial input data register full check
strout(LCD_LINE1, (unsigned char *) strprogmenu);
del1m(2);
strout(LCD_LINE2, (unsigned char *) strprogdev);
while(repeat == '1') {
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
programDEV();
repeat = '0';
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
//LCDMenu();
repeat = '0';
} // end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
//progMenuTime();
repeat = '0';
} //end if LEFT
} //end while repeat
}
void progMenuTime() {
unsigned char repeat = '1';
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strprogmenu);
del1m(2);
strout(LCD_LINE2, (unsigned char *) strsetclk);
while(repeat == '1') {
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
programCLK();
repeat = '0';
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
//progMenuOutlets();
repeat = '0';
} // end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
//LCDMenu();
repeat = '0';
} //end if LEFT
} //end while repeat
}
void progMenuOutlets() {
unsigned char repeat = '1';
clearLCD();
del1m(2);
}
/********************************************* FETCH DEVICE DATA STORED ON
RTC RAM *********************************************/
/*
* ---Time & Date--0x00 = clkRegs[0]: Seconds
0x01 = clkRegs[1]: Minutes
0x02 = clkRegs[2]: Hours
0x03 = clkRegs[3]:
0x04 = clkRegs[4]:
0x05 = clkRegs[5]:
0x06 = clkRegs[6]: Year
0x07 = clkRegs[7]: sqwout....
* ---Storage of On/Off times on RTC:--* Bits 7-4: Hour (1-12)
* Bits 3-1: Minute (0-5, x10)
* Bit 0: AM/PM
* x2 times per device x7 days x4 devices = 56 bytes (total RAM!)
*
* Sunday: 0x08 - 0x0F, offset: (deviceNumber - 1) * 2
Device 1: off: 0x08
Device 1: on: 0x09
Device 2: off: 0x0A
Device 2: on: 0x0B
Device 3: off: 0x0C
Device 3: on: 0x0D
Device 4: off: 0x0E
Device 4: on: 0x0F
* Monday: 0x10 - 0x17
* Tuesday: 0x18 - 0x1F
* Wednesday: 0x20 - 0x27
* Thursday: 0x28 - 0x2F
* Friday: 0x30 - 0x37
* Saturday: 0x38 - 0x3F
//for(x = 8; x > 0; x--) {
// dayData[x-1] = clkRegs[MONREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, MONSTART);
break;
case '3': /********** TUESDAY **********/
//for(x = 8; x > 0; x--) {
//dayData[x-1] = clkRegs[TUEREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, TUESTART);
break;
case '4': /********** WEDNESDAY **********/
//for(x = 8; x > 0; x--) {
//dayData[x-1] = clkRegs[WEDREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, WEDSTART);
break;
case '5': /********** THURSDAY **********/
//for(x = 8; x > 0; x--) {
//dayData[x-1] = clkRegs[THUREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, THUSTART);
break;
case '6': /********** FRIDAY **********/
//for(x = 8; x > 0; x--) {
//dayData[x-1] = clkRegs[FRIREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, FRISTART);
break;
case '7': /********** SATURDAY **********/
//for(x = 8; x > 0; x--) {
//dayData[x-1] = clkRegs[SATREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, SATSTART);
break;
} //end switch
* Get Device Data
* gets and saves updated on/off times for given day
* Reg 1: Off, Reg 2: On
* Bit 7 - 4: Hours (1-12
* Bits 3-1: Minute (0-5, x10)
* Bit 0: AM/PM
*/
void getDevData(unsigned char day) { //day was formerly today, until today was made global
unsigned char x;
unsigned char offset;// = (deviceNum - 1) * 2;
unsigned char i = TOTALDEVS;
//clearLCD();
// (1) read data from clock registers
switch(hexCode[day]) {
case '1': /********** SUNDAY **********/
//for(x = 8; x > 0; x--) {
//teststr[0] = hexCode[x];
//teststr[1] = ' ';
//teststr[2] = hexCode[SUNREG + x - 1];
//teststr[3] = ' ';
//teststr[4] = hexCode[(clkRegs[SUNREG+x-1] >> 4) & 0x0f];
//teststr[5] = hexCode[(clkRegs[SUNREG+x-1]) & 0x0f];
//teststr[6] = '\0';
//strout(LCD_LINE2, teststr);
//del1m(thousand);
// dayData[x-1] = clkRegs[SUNREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, SUNSTART);
break;
case '2': /********** MONDAY **********/
// (2a) process "off" time
if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'A') {
off10hr[i-1] = '1';
off09hr[i-1] = '0';
} else if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'B') {
off10hr[i-1] = '1';
off09hr[i-1] = '1';
} else if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'C') {
off10hr[i-1] = '1';
off09hr[i-1] = '2';
} else {
off10hr[i-1] = '0';
off09hr[i-1] = hexCode[(dayData[offset] >> 4) & 0x0f]; //up to 9
}
offpm[i-1] = hexCode[(dayData[offset] & 0x01)];
offmin[i-1] = hexCode[(dayData[offset] & 0x0e) >> 1]; //all but last bit (bits 3-1)
// (2b) process "on" time
if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'A') {
on10hr[i-1] = '1';
on09hr[i-1] = '0';
} else if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'B') {
on10hr[i-1] = '1';
on09hr[i-1] = '1';
} else if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'C') {
on10hr[i-1] = '1';
on09hr[i-1] = '2';
} else {
on10hr[i-1] = '0';
on09hr[i-1] = hexCode[(dayData[offset+1] >> 4) & 0x0f]; //up to 9
}
onpm[i-1] = hexCode[(dayData[offset+1] & 0x01)];
onmin[i-1] = hexCode[(dayData[offset+1] & 0x0e) >> 1]; //all but last bit (bits 3-1)
/*teststr[0] = off10hr[i - 1];
teststr[1] = off09hr[i - 1];
teststr[2] = ':';
teststr[3] = offmin[i - 1];
teststr[4] = '0';
teststr[5] = offpm[i - 1];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[i - 1];
teststr[9] = on09hr[i - 1];
teststr[10] = ':';
// (2) for each device....
for(; i > 0; i--) { //device 4 --> 3 --> 2 --> 1
offset = (i - 1) * 2; //index offset for dayData, based on device #
//e.g. dev 4 is stored at 6 and 7 (4 - 1 = 3 * 2 = 6)
//e.g. dev 3 is stored at 4 and 5 (3 - 1 = 2 * 2 = 4)
//e.g. dev 2 is stored at 2 and 3 (2 - 1 = 1 * 2 = 2)
//e.g. dev 1 is stored at 0 and 1 (1 - 1 = 0 * 2 = 0)
teststr[11] = onmin[i - 1];
teststr[12] = '0';
teststr[13] = onpm[i - 1];
teststr[14] = 'M';
teststr[15] = '\0';
del1m(thousand); */
} //end for each device
timesToday = day;
}
/********************************************* PROGRAM DEVICE MAIN MENU
*********************************************/
void programDEV() {
unsigned char choice = 0; //0 = exit
unsigned char repeat = 1;
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
while(repeat) {
switch(choice) {
case 0:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) strexit);
break;
case 1:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 1");
break;
case 2:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 2");
break;
case 3:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 3");
break;
case 4:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 4");
break;
default:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet ?");
break;
} //end switch
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
//choice = (choice + 1) % 5;
if(choice == 4)
choice = 0;
else
choice++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
//choice = (choice - 1) % 5;
if(choice == 0)
choice = 4;
else
choice--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//repeat = '0';
if(choice != 0) {
repeat = '0';
programOutlet(choice);
break;
}
} //end if SELECT
break;
case '2': //Monday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strmon);
break;
case '3': //Tuesday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strtue);
break;
case '4': //Wednesday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strwed);
break;
case '5': //Thursday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strthu);
break;
case '6': //Friday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strfri);
break;
case '7': //Saturday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strsat);
break;
default: //unknown??
clearLCD();
del1m(2);
strout(LCD_LINE2, (unsigned char *) strohnoes);
} //end switch(dayofweek)
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
//repeat = 0;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
//repeat = 0;
} //end if LEFT
} //end repeat
}
/********************************************* PROGRAM OUTLET ON/OFF TIME
ON RTC *********************************************/
/* Program Outlet
* User will choose which device to program
* prior to calling this function.
* This function will go through the LCD menus
* to view/change on/off times for outletNum.
*/
void programOutlet(unsigned char outletNum) {
unsigned char repeat = '1', exit = '0';
unsigned char tempvar10, tempvar09, temppm, regOffset, addrOffset, temp;
unsigned char tempchars[8];
tempchars[7] = '\0';
/* CHANGE DAY OF THE WEEK */
while(exit == '0') {
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strprogday);
today = 0; //start at exit --> user can choose a day of the week from there
repeat = '1';
while(repeat == '1') {
del1m(100);
switch(hexCode[today]) {
case '0': //done/exit
del1m(2);
strout(LCD_LINE2, (unsigned char *) strexit);
break;
case '1': //Sunday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strsun);
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = '0';
if(today == 0) { //exit back to choose outlet
exit = '1';
//programDEV();
}
else { //no exit
//del1m(thousand);
getDevData(today); //update all the variablesssssss
regOffset = (outletNum - 1) * 2;
//addrOffset = (regOffset >> 4) & 0x0f;
addrOffset = (regOffset) & 0x0f;
}
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
} //end while(repeat)
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(today == 7)
today = 0; //--> exit
else
today++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(today == 0)
today = 7;
else
today--;
} //end if DOWN
else if(SELECT) {
if(exit == '1') {
break;
}
/* CHANGE OFF HOUR */
clearLCD();
repeat = '1';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroffhour);
tempvar10 = off10hr[outletNum - 1];
tempvar09 = off09hr[outletNum - 1];
if(offpm[outletNum - 1] == '0')
temppm = 'A';
else if(offpm[outletNum - 1] == '1')
temppm = 'P';
else
temppm = '?';
while(repeat == '1') {
del1m(100);
tempchars[0] = tempvar10;
tempchars[1] = tempvar09;
tempchars[2] = temppm;
tempchars[3] = 'M';
tempchars[4] = '\0';
del1m(2);
strout(LCD_LINE2, tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12
if(tempvar09 == '2') { //12AM --> 01AM, 12PM --> 01PM
tempvar09 = '1';
tempvar10 = '0';
} //end if 12
else { //its 10 or 11
if(tempvar09 == '1') { //11PM --> 12AM, 11AM --> 12PM
if(temppm == 'A') temppm = 'P';
else if(temppm == 'P') temppm = 'A';
} //end if 11
tempvar09++;
} //end if 10 or 11
} //end hour MSB is 1
else if(tempvar10 == '0') { //its 01-09
if(tempvar09 == '9') { //9AM --> 10AM, 9PM --> 10PM
tempvar09 = '0';
tempvar10 = '1';
} //end if tempvar09 == 9
else { //tempvar09 between 1 and 8 --> just increment by 1
tempvar09++;
}
} //end hour MSB is 0
} //end if UP
else if(DOWN) {
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset], 1,
SUNSTART + addrOffset);
break;
case '2': //Monday
clkRegs[MONREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset],
1, MONSTART + addrOffset);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset], 1,
TUESTART + addrOffset);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset],
1, WEDSTART + addrOffset);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset],
1, THUSTART + addrOffset);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset], 1,
FRISTART + addrOffset);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset], 1,
SATSTART + addrOffset);
break;
} //end switch(today)
//*/
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12
if(tempvar09 == '0') { //10AM --> 09AM, 10PM --> 09PM
tempvar09 = '9';
tempvar10 = '0';
} //end if 10
else { //its 11 or 12
if(tempvar09 == '2') { //12PM --> 11AM, 12AM --> 11PM
if(temppm == 'A') temppm = 'P';
else if(temppm == 'P') temppm = 'A';
}
tempvar09--;
} //end if 11 or 12
} //end hour MSB is 1
else if (tempvar10 == '0') { //its 01-09
if(tempvar09 == '1') { //01AM --> 12AM, 01PM --> 12PM
tempvar09 = '2'; //tempvar09++;
tempvar10 = '1';
}
else { //its between 02 and 09 --> just decrement by 1
tempvar09--;
}
} //end hour MSB is 0
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
// (1) update clkRegs for this device, day
// (2) update RTC regs with i2c_write2
off10hr[outletNum - 1] = tempvar10;
off09hr[outletNum - 1] = tempvar09;
if(temppm == 'A')
offpm[outletNum - 1] = '0';
else if(temppm == 'P')
offpm[outletNum - 1] = '1';
temp = ((((off10hr[outletNum - 1]*10) + off09hr[outletNum - 1]) & 0x0f) << 4) |
(((offmin[outletNum - 1] & 0x07) << 1) | (offpm[outletNum - 1] & 0x01)); //1001 0000 = 0x90
// /*
del1m(100);
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset] = temp;
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//end while(repeat)
/* CHANGE OFF MINUTE */
//choose among: 00, 10, 20, 30, 40, 50
clearLCD();
repeat = '1';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
tempvar09 = '0';
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroffmin);
tempvar10 = offmin[outletNum - 1];
while(repeat == '1') {
del1m(100);
tempchars[0] = off10hr[outletNum - 1];
tempchars[1] = off09hr[outletNum - 1];
tempchars[2] = ':';
tempchars[3] = tempvar10;
tempchars[4] = '0';
if(offpm[outletNum - 1] == '0')
tempchars[5] = 'A';
else if(offpm[outletNum - 1] == '1')
tempchars[5] = 'P';
else
tempchars[5] = '?';
tempchars[6] = 'M';
tempchars[7] = '\0';
del1m(2);
strout(LCD_LINE2, tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
//tempvar10 = (tempvar10 + 1)%6;
if(tempvar10 == '5') tempvar10 = '0';
else tempvar10++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
//tempvar10 = (tempvar10 - 1)%6;
if(tempvar10 == '0') tempvar10 = '5';
else tempvar10--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
// (1) update clkRegs for this device, day
// (2) update RTC regs with i2c_write2
offmin[outletNum - 1] = tempvar10;
// /*
temp = ((((off10hr[outletNum - 1]*10) + off09hr[outletNum - 1]) & 0x0f) << 4) |
(((offmin[outletNum - 1] & 0x07) << 1) | (offpm[outletNum - 1] & 0x01)); //1001 0000 = 0x90
del1m(100);
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset], 1,
SUNSTART + addrOffset);
break;
case '2': //Monday
clkRegs[MONREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset],
1, MONSTART + addrOffset);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset], 1,
TUESTART + addrOffset);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset],
1, WEDSTART + addrOffset);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset],
1, THUSTART + addrOffset);
break;
case '6': //Friday
temppm = 'P';
else
temppm = '?';
while(repeat == '1') {
del1m(100);
tempchars[0] = tempvar10;
tempchars[1] = tempvar09;
tempchars[2] = temppm;
tempchars[3] = 'M';
tempchars[4] = '\0';
del1m(2);
strout(LCD_LINE2, tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12
if(tempvar09 == '2') { //12AM --> 01AM, 12PM --> 01PM
tempvar09 = '1';
tempvar10 = '0';
} //end if 12
else { //its 10 or 11
if(tempvar09 == '1') { //11PM --> 12AM, 11AM --> 12PM
if(temppm == 'A') temppm = 'P';
else if(temppm == 'P') temppm = 'A';
} //end if 11
tempvar09++;
} //end if 10 or 11
} //end hour MSB is 1
else if(tempvar10 == '0') { //its 01-09
if(tempvar09 == '9') { //9AM --> 10AM, 9PM --> 10PM
tempvar09 = '0';
tempvar10 = '1';
} //end if tempvar09 == 9
else { //tempvar09 between 1 and 8 --> just increment by 1
tempvar09++;
}
} //end hour MSB is 0
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12
if(tempvar09 == '0') { //10AM --> 09AM, 10PM --> 09PM
tempvar09 = '9';
tempvar10 = '0';
clkRegs[FRIREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset], 1,
FRISTART + addrOffset);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset], 1,
SATSTART + addrOffset);
break;
} //end switch(today)
//*/
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//end while(repeat)
/* CHANGE ON HOUR */
clearLCD();
repeat = '1';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
tempchars[4] = ' ';
tempchars[5] = ' ';
tempchars[6] = ' ';
del1m(2);
strout(LCD_LINE1, (unsigned char *) stronhour);
tempvar10 = on10hr[outletNum - 1];
tempvar09 = on09hr[outletNum - 1];
if(onpm[outletNum - 1] == '0')
temppm = 'A';
else if(onpm[outletNum - 1] == '1')
} //end if 10
else { //its 11 or 12
if(tempvar09 == '2') { //12PM --> 11AM, 12AM --> 11PM
if(temppm == 'A') temppm = 'P';
else if(temppm == 'P') temppm = 'A';
}
tempvar09--;
} //end if 11 or 12
} //end hour MSB is 1
else if (tempvar10 == '0') { //its 01-09
if(tempvar09 == '1') { //01AM --> 12AM, 01PM --> 12PM
tempvar09 = '2'; //tempvar09++;
tempvar10 = '1';
}
else { //its between 02 and 09 --> just decrement by 1
tempvar09--;
}
} //end hour MSB is 0
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
// (1) update clkRegs for this device, day
// (2) update RTC regs with i2c_write2
on10hr[outletNum - 1] = tempvar10;
on09hr[outletNum - 1] = tempvar09;
if(temppm == 'A')
onpm[outletNum - 1] = '0';
else if(temppm == 'P')
onpm[outletNum - 1] = '1';
// /*
temp = ((((on10hr[outletNum - 1]*10) + on09hr[outletNum - 1]) & 0x0f) << 4) |
(((onmin[outletNum - 1] & 0x07) << 1) | (onpm[outletNum - 1] & 0x01)); //0110 0110 = 0x66
del1m(100);
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset +
1], 1, SUNSTART + addrOffset + 0x01);
break;
case '2': //Monday
clkRegs[MONREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset +
1], 1, MONSTART + addrOffset + 0x01);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset +
1], 1, TUESTART + addrOffset + 0x01);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset +
1], 1, WEDSTART + addrOffset + 0x01);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset +
1], 1, THUSTART + addrOffset + 0x01);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset +
1], 1, FRISTART + addrOffset + 0x01);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset +
1], 1, SATSTART + addrOffset + 0x01);
break;
} //end switch(today)
//*/
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//end while(repeat)
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
// (1) update clkRegs for this device, day
// (2) update RTC regs with i2c_write2
onmin[outletNum - 1] = tempvar10;
// /*
temp = ((((on10hr[outletNum - 1]*10) + on09hr[outletNum - 1]) & 0x0f) << 4) |
(((onmin[outletNum - 1] & 0x07) << 1) | (onpm[outletNum - 1] & 0x01)); //0110 0110 = 0x66
del1m(100);
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset +
1], 1, SUNSTART + addrOffset + 0x01);
break;
case '2': //Monday
clkRegs[MONREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset +
1], 1, MONSTART + addrOffset + 0x01);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset +
1], 1, TUESTART + addrOffset + 0x01);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset +
1], 1, WEDSTART + addrOffset + 0x01);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset +
1], 1, THUSTART + addrOffset + 0x01);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset +
1], 1, FRISTART + addrOffset + 0x01);
break;
/* CHANGE ON MINUTE */
//choose among: 00, 10, 20, 30, 40, 50
clearLCD();
repeat = '1';
tempvar09 = '0';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
del1m(2);
strout(LCD_LINE1, (unsigned char *) stronmin);
tempvar10 = onmin[outletNum - 1];
while(repeat == '1') {
del1m(100);
tempchars[0] = on10hr[outletNum - 1];
tempchars[1] = on09hr[outletNum - 1];
tempchars[2] = ':';
tempchars[3] = tempvar10;
tempchars[4] = '0';
if(onpm[outletNum - 1] == '0')
tempchars[5] = 'A';
else if(onpm[outletNum - 1] == '1')
tempchars[5] = 'P';
else
tempchars[5] = '?';
tempchars[6] = 'M';
tempchars[7] = '\0';
del1m(2);
strout(LCD_LINE2, tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
//tempvar10 = (tempvar10 + 1)%6;
if(tempvar10 == '5') tempvar10 = '0';
else tempvar10++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
//tempvar10 = (tempvar10 - 1)%6;
if(tempvar10 == '0') tempvar10 = '5';
else tempvar10--;
} //end if DOWN
case '7': //Saturday
clkRegs[SATREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset +
1], 1, SATSTART + addrOffset + 0x01);
break;
} //end switch(today)
//*/
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//end while(repeat)
//TEST//
del1m(1);
getDevData(today);
teststr[0] = off10hr[outletNum - 1];
teststr[1] = off09hr[outletNum - 1];
teststr[2] = ':';
teststr[3] = offmin[outletNum - 1];
teststr[4] = '0';
teststr[5] = offpm[outletNum - 1];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[outletNum - 1];
teststr[9] = on09hr[outletNum - 1];
teststr[10] = ':';
teststr[11] = onmin[outletNum - 1];
teststr[12] = '0';
teststr[13] = onpm[outletNum - 1];
teststr[14] = 'M';
teststr[15] = '\0';
del1m(2);
strout(LCD_LINE1, "is this what you saved?");
del1m(2);
strout(LCD_LINE2, teststr);
while(!SELECT) {} //so can look at
while(SELECT) {} //debounce
//TEST//
repeat = '1'; //go back into choosing day of the week
} //while !exit
strout(LCD_LINE2, (unsigned char *) strthu);
break;
case '6': //Friday
strout(LCD_LINE2, (unsigned char *) strfri);
break;
case '7': //Saturday
strout(LCD_LINE2, (unsigned char *) strsat);
break;
default: //unknown??
strout(LCD_LINE2, (unsigned char *) strohnoes);
} //end switch(dayofweek)
}
/********************************************* PROGRAM THE DATE AND TIME
ON RTC *********************************************/
/* Program Clock
* This function will go through the LCD menus
* to view/change the set time and date.
*/
void programCLK() {
unsigned char repeat = '1';
unsigned char tempvar, tempvar10, tempvar09, temppm;
unsigned char tempchars[5] = " ";
tempchars[4] = '\0';
getTime(); //get initial values
/* CHANGE DAY OF THE WEEK */
clearLCD();
strout(LCD_LINE1, (unsigned char *) strweekday);
tempvar = hexCode[dayofweek];
while(repeat == '1') {
switch(tempvar) {
case '1': //Sunday
strout(LCD_LINE2, (unsigned char *) strsun);
break;
case '2': //Monday
strout(LCD_LINE2, (unsigned char *) strmon);
break;
case '3': //Tuesday
strout(LCD_LINE2, (unsigned char *) strtue);
break;
case '4': //Wednesday
strout(LCD_LINE2, (unsigned char *) strwed);
break;
case '5': //Thursday
} //while(repeat)
/* CHANGE MONTH */
clearLCD();
repeat = '1';
strout(LCD_LINE1, (unsigned char *) strmonth);
tempvar10 = hexCode[months10];
tempvar09 = hexCode[months09];
while(repeat == '1') {
if(tempvar10 == '1') {
switch(tempvar09) {
case '0': //10 October
strout(LCD_LINE2, (unsigned char *) stroct);
break;
case '1': //11 November
strout(LCD_LINE2, (unsigned char *) strnov);
break;
case '2': //12 December
strout(LCD_LINE2, (unsigned char *) strdec);
break;
} //end switch(months09)
} //end if months10 == 1
else { //months10 == 0
switch(tempvar09) {
case '1': //1 January
strout(LCD_LINE2, (unsigned char *) strjan);
break;
case '2': //2 February
strout(LCD_LINE2, (unsigned char *) strfeb);
break;
case '3': //3 March
strout(LCD_LINE2, (unsigned char *) strmar);
break;
case '4': //4 April
strout(LCD_LINE2, (unsigned char *) strapr);
break;
case '5': //5 May
strout(LCD_LINE2, (unsigned char *) strmay);
break;
case '6': //6 June
strout(LCD_LINE2, (unsigned char *) strjun);
break;
case '7': //7 July
strout(LCD_LINE2, (unsigned char *) strjul);
break;
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar == '7') //saturday
tempvar = '1'; //--> sunday
else
tempvar++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar == '1') //sunday
tempvar = '7'; //--> saturday
else
tempvar--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
clkRegs[3] = ((tempvar) & 0x0f);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[3], 1, 3);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
case '8': //8 August
strout(LCD_LINE2, (unsigned char *) straug);
break;
case '9': //9 September
strout(LCD_LINE2, (unsigned char *) strsep);
break;
default: //unknown??
strout(LCD_LINE2, (unsigned char *) strohnoes);
} //end switch(months09)
} //end else months10 == 0
//while(!UP && !DOWN && !SELECT);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar10 == '1') {
if(tempvar09 == '0' || tempvar09 == '1') tempvar09++;
else { //12 December --> 01 January
tempvar10 = '0';
tempvar09 = '1';
} //months09 != 0
} //months10 ==1
else { //months10 == 0
if(tempvar09 <= '8') tempvar09++;
else { //09 September --> 10 October
tempvar10 = '1';
tempvar09 = '0';
} //months09 > 8
} //months10 == 1
} //if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar10 == '1') {
if(tempvar09 == '2' || tempvar09 == '1') tempvar09--;
else { //10 October --> 09 September
tempvar10 = '0';
tempvar09 = '9';
}
} //months10 ==1
else {
if(tempvar09 > '1') tempvar09--;
else { //01 January --> 12 December
tempvar10 = '1';
tempvar09 = '2';
} //else months09 == 1
} //else months10 == 0
} //if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
clkRegs[5] = (((0x0f & tempvar10) << 4) | (0x0f & tempvar09));
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[5], 1, 5);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//while(repeat)
/* CHANGE DAY OF THE MONTH */
clearLCD();
repeat = '1';
strout(LCD_LINE1, (unsigned char *) strdate);
tempvar10 = hexCode[date10];
tempvar09 = hexCode[date09];
while(repeat == '1') {
tempchars[0] = tempvar10;
tempchars[1] = tempvar09;
strout(LCD_LINE2, (unsigned char *) tempchars);
//while(!UP && !DOWN && !SELECT);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar10 == '3') { //31 days: jan (01), march (03), may (05), july (07), oct (10), dec (12);
30 days: april (04), june (06), aug (08), sept (09), nov (11)
if(hexCode[months10] == '0') {
if(hexCode[months09] == '2' || hexCode[months09] == '4' || hexCode[months09] == '6') {
//if february, april, june
tempvar10 = '0';
tempvar09 = '1';
}
else if(hexCode[months09] == '1' || hexCode[months09] == '3' || hexCode[months09] ==
'5' || hexCode[months09] == '7') { //january, march, may, july
tempvar09++;
}
} //end if date10 == 1 || 0
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar10 == '0' && tempvar09 == '1') {
if(hexCode[months10] == '0') { //months: january-september
if(hexCode[months09] == '2') { //february --> max 29 days
tempvar10 = '2';
tempvar09 = '9';
} //end if february
else if(hexCode[months09] == '1' || hexCode[months09] == '3' || hexCode[months09] ==
'5' || hexCode[months09] == '7' || hexCode[months09] == '8') { //months with 31 days (jan, mar,
may, july, aug)
tempvar10 == '3';
tempvar09 == '1';
} //end if month with 31 days
else if(hexCode[months09] == '4' || hexCode[months09] == '6' || hexCode[months09] ==
'9') { //months with 30 days (april, june, sept)
tempvar10 == '3';
tempvar09 == '0';
} //end if month with 30 days
} //end if months10 = 0
else if(hexCode[months10] == '1') {
if(hexCode[months09] == '1') { //november has 30 days
tempvar10 = '3';
tempvar09 = '0';
}
else if(hexCode[months09] == '0' || hexCode[months09] == '2') { //october and december
have 31 days
tempvar10 = '3';
tempvar09 = '1';
}
} //end if months10 = 1
} //end if date == 01
else if(date09 == 0) { //date != 01, date09 == 0
tempvar10--;
tempvar09--;
}
else { //date != 01, date09 > 0
tempvar09--;
}
} //if DOWN
if(tempvar09 == '1') {
tempvar10 = '0';
tempvar09 = '1';
}
else if(tempvar09 == '0') {
tempvar09 = '1';
}
} //end if january, march, may, july
} //end if months10 == 0 (january - september except february)
else if(hexCode[months10] == '1') {
if(hexCode[months09] == '1') { //november
tempvar10 = '0';
tempvar09 = '1';
}
else if(hexCode[months09] == '0' || hexCode[months09] == '2') { //october or december
if(tempvar09 == '1') {
tempvar10 = '0';
tempvar09 = '1';
}
else if(tempvar09 == '0') { tempvar09 = '1'; }
} //end if months10 == 1 (october or november or december)
} //end if months10 == 1
} //end if date10 == 3
else if(tempvar10 == '2') {
if(tempvar09 == '9') {
if(hexCode[months10] == '0' && hexCode[months09] == '2') { //february
tempvar10 = '0';
tempvar09 = '1';
}
else { //not february
tempvar10 = '3';
tempvar09 = '0';
}
} //end if date09 == 9
else { //date09 < 9
tempvar09++;
} //end if date09 < 9
} //end if date10 == 2
else if(tempvar10 == '1' || tempvar10 == '0') { //date10 = 1 or 0
if(tempvar09 == '9') {
tempvar10++;
tempvar09 = '0';
} //end if date09 == 9
else {
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
clkRegs[4] = (((0x0f & tempvar10) << 4) | (0x0f & tempvar09));
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[4], 1, 4);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//while(repeat)
/* CHANGE YEAR */
clearLCD();
repeat = '1';
strout(LCD_LINE1, (unsigned char *) stryear);
tempchars[0] = '2';
tempchars[1] = '0';
tempvar10 = hexCode[years10];
tempvar09 = hexCode[years09];
while(repeat == '1') {
tempchars[2] = tempvar10;
tempchars[3] = tempvar09;
strout(LCD_LINE2, (unsigned char *) tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar09 == '9') {
tempvar09 = '0';
if(tempvar10 == '9') tempvar10 = '0';
else tempvar10++;
} //end years09 == 9
else tempvar09++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar09 == '0') {
tempvar09 = '9';
if(tempvar10 == '0') tempvar10 = '9';
else tempvar10--;
} //end years09 == 0
else tempvar09--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
clkRegs[6] = (((0x0f & tempvar10) << 4) | (0x0f & tempvar09));
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[6], 1, 6);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
} //end while(repeat)
/* CHANGE HOUR */
clearLCD();
repeat = '1';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
strout(LCD_LINE1, (unsigned char *) strtimehr);
tempvar10 = hexCode[hours10];
tempvar09 = hexCode[hours09];
tempchars[0] = tempvar10; //NEW//
tempchars[1] = tempvar09;
if(hexCode[pm] == '1') temppm = 'P'; //NEW//
else { //its 11 or 12
if(tempvar09 == '2') { //12PM --> 11AM, 12AM --> 11PM
//OLD//if(tempvar10 == '3') tempvar10 = '1';
//OLD//else if(tempvar10 == '1') tempvar10 = '3';
if(temppm == 'A') temppm = 'P'; //NEW//
else if(temppm == 'P') temppm = 'A'; //NEW//
}
tempvar09--;
} //end if 11 or 12
} //end hour MSB is 1s
else if(tempvar10 == '0') { //its 01-09 //NEW//
if(tempvar09 == '1') { //01AM --> 12AM, 01PM --> 12PM
tempvar09 = '2'; //tempvar09++;
tempvar10 = '1';
}
else { //its between 02 and 09 --> just decrement by 1
tempvar09--;
}
} //end hour MSB is 0
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
if(temppm == 'A')
pm = 0;
else
pm = 1;
clkRegs[2] = (((0x01 & pm) << 5) | ((0x01 & tempvar10) << 4) | (0x0f & tempvar09));
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[2], 1, 2);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//end while(repeat)
else temppm = 'A'; //NEW//
tempchars[2] = temppm;
tempchars[3] = 'M';
while(repeat == '1') {
tempchars[0] = tempvar10; //NEW//
tempchars[1] = tempvar09;
tempchars[2] = temppm; //NEW//
tempchars[3] = 'M';
strout(LCD_LINE2, (unsigned char *) tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12 //NEW//
if(tempvar09 == '2') { //12AM --> 01AM, 12PM --> 01PM
tempvar09 = '1';
tempvar10 = '0';
} //end if 12
else { //its 10 or 11
if(tempvar09 == '1') { //11PM --> 12AM, 11AM --> 12PM
//OLD//if(tempvar10 == '1') tempvar10 = '3';
//OLD//else if(tempvar10 == '3') tempvar10 = '1';
if(temppm == 'A') temppm = 'P'; //NEW//
else if(temppm == 'P') temppm = 'A'; //NEW//
}
tempvar09++;
} //end if 10 or 11
} //end hour MSB is 1
else if(tempvar10 == '0') { //its 01-09 //NEW//
if(tempvar09 == '9') {
tempvar09 = '0';
tempvar10 = '1'; //9AM --> 10AM, 9PM --> 10PM
} //end if tempvar09 == 9
else { //tempvar09 between 1 and 8 --> just increment by 1
tempvar09++;
}
} //end hour MSB is 0
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12
if(tempvar09 == '0') { //10AM --> 09AM, 10PM --> 09PM
tempvar09 = '9';
tempvar10 = '0';
} //end if 10
/* CHANGE MINUTE */
clearLCD();
repeat = '1';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
strout(LCD_LINE1, (unsigned char *) strtimemin);
tempvar10 = hexCode[minutes10];
tempvar09 = hexCode[minutes09];
while(repeat == '1') {
tempchars[0] = tempvar10;
tempchars[1] = tempvar09;
strout(LCD_LINE2, (unsigned char *) tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar09 == '9') {
if(tempvar10 == '5') {
tempvar10 = '0';
tempvar09 = '0';
}
else { //minutes10 < 5 && minutes09 == 9
tempvar10++;
tempvar09 = '0';
}
}
else { //minutes09 < 9
tempvar09++;
}
} //end UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar09 == '0') {
if(tempvar10 == '0') {
tempvar10 = '5';
tempvar09 = '9';
}
else { //minutes10 > 0 && minutes09 == 0
tempvar10--;
tempvar09 = '9';
}
}
else { //minutes09 > 0
tempvar09--;
}
} //end DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
del1m(1);
i2c_read2(CLOCK_RD_ADDR, clkRegs, 8, 0); //read all 8 main registers
// day of the week
dayofweek = (clkRegs[3] & 0x07); //only care about 3 lowest bits
switch(hexCode[dayofweek]) {
case '1': //Sunday
time[0] = 'S';
time[1] = 'u';
time[2] = 'n';
break;
case '2': //Monday
time[0] = 'M';
time[1] = 'o';
time[2] = 'n';
break;
case '3': //Tuesday
time[0] = 'T';
time[1] = 'u';
time[2] = 'e';
break;
case '4': //Wednesday
time[0] = 'W';
time[1] = 'e';
time[2] = 'd';
break;
case '5': //Thursday
time[0] = 'T';
time[1] = 'h';
time[2] = 'u';
break;
case '6': //Friday
time[0] = 'F';
time[1] = 'r';
time[2] = 'i';
break;
case '7': //Saturday
time[0] = 'S';
time[1] = 'a';
time[2] = 't';
break;
//update the clock register
clkRegs[1] = (((0x0f & tempvar10) << 4) | (0x0f & tempvar09));
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[1], 1, 1);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
} //end while(repeat)
strout(LCD_LINE1, "Select to Return Home");
while(!SELECT) {
testCLK();
del1m(1000);
}
while(SELECT){} //debounce
}
/* This program tests the DS1307 Real Time Clock with I2C interface
* An LED on pin 2 of the MC908JL16 will blink every other second
* An LED connected to the SQW output of the Clock will blink at 1Hz
* The LCD will display the time
*/
void testCLK() {
//unsigned char time[24]; //Day, MO/DD/YR HH:MM xm
time[23] = '\0';
default: //unknown??
time[0] = '?';
time[1] = '?';
time[2] = '?';
}
time[3] = ',';
time[4] = ' ';
time[19] = ':';
seconds10 = ((clkRegs[0] >> 4) & 0x07); //only 3 10's bits
seconds09 = (clkRegs[0] & 0x0f);
time[20] = hexCode[seconds10];
time[21] = hexCode[seconds09];
if(hexCode[pm] == '0')
time[22] = 'A';
else if(hexCode[pm] == '1')
time[22] = 'P';
else
time[22] = '?';
time[23] = 'M';
//month
months10 = (clkRegs[5] >> 4) & 0x01; //only 1 10's bit
months09 = (clkRegs[5] & 0x0f);
time[5] = hexCode[months10];
time[6] = hexCode[months09];
time[7] = '/';
//day of the month
date10 = (clkRegs[4] >> 4) & 0x03; //only 2 10's bits
date09 = (clkRegs[4] & 0x0f);
time[8] = hexCode[date10];
time[9] = hexCode[date09];
time[10] = '/';
//year
years10 = (clkRegs[6] >> 4) & 0x0f;
years09 = (clkRegs[6] & 0x0f);
time[11] = hexCode[years10];
time[12] = hexCode[years09];
time[13] = ' ';
//hour
/*if((hexCode[(clkRegs[2] >> 4) & 0x0f] == '0') || (hexCode[(clkRegs[2] >> 4) & 0x0f] == '1'))
{
pm = 'A';
}
else if((hexCode[(clkRegs[2] >> 4) & 0x0f] == '2') || (hexCode[(clkRegs[2] >> 4) & 0x0f] ==
'3')) {
pm = 'P';
} */
pm = ((clkRegs[2] >> 5) & 0x01);
hours10 = (clkRegs[2] >> 4) & 0x01; //1st bit only - //NEW//
hours09 = (clkRegs[2] & 0x0f);
time[14] = hexCode[hours10]; //NEW//
time[15] = hexCode[hours09];
time[16] = ':';
//minute
minutes10 = (clkRegs[1] >> 4) & 0x07; //only 3 10's bits
minutes09 = (clkRegs[1] & 0x0f);
time[17] = hexCode[minutes10];
time[18] = hexCode[minutes09];
del1m(2);
strout(LCD_LINE2, (unsigned char *) time);
}
/* Get Time
* Retrieves Time & Date Register Values
* Saves to Global Variables
*/
void getTime() {
i2c_read2(CLOCK_RD_ADDR, clkRegs, 7, 0);
seconds10 = ((clkRegs[0] >> 4) & 0x07); //only 3 10's bits
seconds09 = (clkRegs[0] & 0x0f);
minutes10 = (clkRegs[1] >> 4) & 0x07; //only 3 10's bits
minutes09 = (clkRegs[1] & 0x0f);
pm = ((clkRegs[2] >> 5) & 0x01);
hours10 = (clkRegs[2] >>4) & 0x01; //1st bit only - //NEW//
hours09 = (clkRegs[2] & 0x0f);
dayofweek = (clkRegs[3] & 0x07); //only care about 3 lowest bits
date10 = (clkRegs[4] >> 4) & 0x03; //only 2 10's bits
date09 = (clkRegs[4] & 0x0f);
months10 = (clkRegs[5] >> 4) & 0x01; //only 1 10's bit
months09 = (clkRegs[5] & 0x0f);
years10 = (clkRegs[6] >> 4) & 0x0f;
years09 = (clkRegs[6] & 0x0f);
}
/* ----------------------------------------------------------------------- */
/**************************************** Test Functions
****************************************/
/* turn on LED in port A bit 0 for n msec, then turn off */
void blink(int n) {
PTA_PTA0 = 0; //turn on LED
del1m(n); //leave on n msec
PTA_PTA0 = 1; //turn off LED
}
/*
void testOutlets() {
del1m(2);
while(one) {
OUTLET1 = 1;
strout(LCD_LINE1, "outlet 1");
del1m(thousand);
OUTLET1 = 0;
OUTLET2 = 1;
strout(LCD_LINE1, "outlet 2");
del1m(thousand);
OUTLET2 = 0;
OUTLET3 = 1;
strout(LCD_LINE1, "outlet 3");
del1m(thousand);
OUTLET3 = 0;
/* Clear Contents of LCD:
* Bring cursor home
* Print blanks on line 1
* Print Blanks on line 2
* Bring cursor home
*/
void clearLCD() {
del1m(2);
strout(LCD_LINE1, (unsigned char *) clearstr); // clear line 1
del1m(2);
strout(LCD_LINE2, (unsigned char *) clearstr); //clear line 2
cmdout(0x02); //cursor home
}
/* charout - Print the character 'c' at LCD RAM location "x". */
void charout(int x, unsigned char c) {
unsigned char ch;
cmdout(x | 0x80); // Make A contain a Set Display Address command
while ((ch = c) != (unsigned char) NULL) {
datout(c); // Output the next character
}
}
/* strout - Print the contents of the character string "s" starting at LCD
RAM location "x". The string must be terminated by a zero byte. */
void strout(int x, unsigned char *s) {
unsigned char ch;
cmdout(x | 0x80); // Make A contain a Set Display Address command
OUTLET4 = 1;
strout(LCD_LINE1, "outlet 4");
del1m(thousand);
OUTLET4 = 0;
}
}*/
while ((ch = *s++) != (unsigned char) NULL) {
datout(ch); // Output the next character
}
}
/**************************************** Test Functions
****************************************/
/**************************************** LCD
****************************************/
/* datout - Output a byte to the LCD display data register (the display)
and wait for the busy flag to reset. */
void datout(unsigned char x) {
PTD = 0x02;
// Set R/W=0, E=0, RS=1
nibout(x);
// Put data bits 4-7 in PTB
nibout(x << 4); // Put data bits 0-3 in PTB
busywt();
// Wait for BUSY flag to reset
}
iniout(0x30);
/* cmdout - Output a byte to the LCD display instruction register and
wait for the busy flag to reset. */
void cmdout(unsigned char x) {
PTD = 0;
// Set R/W=0, E=0, RS=0
nibout(x);
// Output command bits 4-7
nibout(x << 4); // Output command bits 0-3
busywt();
// Wait for BUSY flag to reset
}
/* nibout - Puts bits 4-7 from x into the four bits of Port B that we're
using to talk to the LCD. The other bits of Port B are unchanged.
Toggle the E control line low-high-low. */
void nibout(unsigned char x) {
#ifdef NIBBLE_HIGH
PTB = (x & 0xf0) | (PTB & 0x0f); // Use bits 4-7
//PTB_PTB4 = x & 0x10;
//PTB_PTB5 = x & 0x20;
//PTB_PTB6 = x & 0x30;
//PTB_PTB7 = x & 0x80;
#else
PTB = ((x >> 4) & 0x0f) | (PTB & 0xf0); // Use bits 0-3
//PTB_PTB0 = x & 0x01;
//PTB_PTB1 = x & 0x02;
//PTB_PTB2 = x & 0x04;
//PTB_PTB3 = x & 0x08;
#endif
PTD_PTD3 = 1;
// Set E to 1
PTD_PTD3 = 0;
// Set E to 0
}
/* initialize - Do various things to force a initialization of the LCD
display by instructions, and then set up the display parameters and
turn the display on. */
void initializeLCD() {
del1m(15);
// Delay at least 15ms
iniout(0x30);
del1m(4);
// Send a 0x30
// Delay at least 4msec
iniout(0x30);
del40u(3);
// Send a 0x30
// Delay at least 100usec
iniout(0x20);
busywt();
// Send a 0x30
// Function Set: 4-bit interface
// Wait for BUSY flag to reset
cmdout(0x28);
// Function Set: 4-bit interface, 2 lines
cmdout(0x0f);
// Display and cursor on
}
/* iniout - Output a byte to the LCD control register. Same as the "cmdout"
function but it doesn't wait for the BUSY flag since that flag isn't
working during initialization. */
void iniout(unsigned char x) {
PTD = 0;
// Set R/W=0, E=0, RS=0
nibout(x);
}
/* busywt - Wait for the BUSY flag to reset */
void busywt() {
unsigned char bf;
//DDRB = 0;
// Set PTB for input
DDRB_DDRB4 = 0;
DDRB_DDRB5 = 0;
DDRB_DDRB6 = 0;
DDRB_DDRB7 = 0;
PTD = 0x04;
// Set E=0, R/W=1, RS=0
do {
PTD_PTD3 = 1; // Set E=1
#ifdef NIBBLE_HIGH
bf = PTB & 0x80; // Read status register bits 4-7
#else
bf = PTB & 0x08; // Read status register bits 4-7
#endif
PTD_PTD3 = 0; // Set E=0
PTD_PTD3 = 1; // Set E=1, ignore bits 0-3
PTD_PTD3 = 0; // Set E=0
} while (bf != 0); // If Busy (PTB7=1), loop
#ifdef NIBBLE_HIGH
//DDRB = 0xf0;
// Set PTB for output
DDRB_DDRB4 = 1;
DDRB_DDRB5 = 1;
DDRB_DDRB6 = 1;
DDRB_DDRB7 = 1;
#else
//DDRB = 0x0f;
// Set PTB for output
DDRB_DDRB0 = 1;
DDRB_DDRB1 = 1;
DDRB_DDRB2 = 1;
DDRB_DDRB3 = 1;
#endif
}
//the rest: RAM (on/off times)
clkRegs[8] = clkRegs[9] = 0xC0;
clkRegs[10] = clkRegs[11] = clkRegs[12] = clkRegs[13] = clkRegs[14] = clkRegs[15] =
clkRegs[16] = clkRegs[17] = clkRegs[18] = clkRegs[19] = 0xC0;
clkRegs[20] = clkRegs[21] = clkRegs[22] = clkRegs[23] = clkRegs[24] = clkRegs[25] =
clkRegs[26] = clkRegs[27] = clkRegs[28] = clkRegs[29] = 0xC0;
clkRegs[30] = clkRegs[31] = clkRegs[32] = clkRegs[33] = clkRegs[34] = clkRegs[35] =
clkRegs[36] = clkRegs[37] = clkRegs[38] = clkRegs[39] = 0xC0;
clkRegs[40] = clkRegs[41] = clkRegs[42] = clkRegs[43] = clkRegs[44] = clkRegs[45] =
clkRegs[46] = clkRegs[47] = clkRegs[48] = clkRegs[49] = 0xC0;
clkRegs[50] = clkRegs[51] = clkRegs[52] = clkRegs[53] = clkRegs[54] = clkRegs[55] = 0xC0;
/**************************************** LCD
****************************************/
i2c_write2(CLOCK_WR_ADDR, clkRegs, 64, 0);
}
/**************************************** I2C - Real Time Clock
****************************************/
/* i2c_init - Initialize the MMIIC port */
void i2c_init(unsigned char bdiv) {
MIMCR_MMBR = bdiv;
// Set baud rate divisor
MMCR_MMEN = 1;
// Enable MMIIC
}
/* clk_init - Initialize the Clock
* The Clock is initialized to 12:00:00 PM Wednesday 04/01/09
* The SQWE pin outputs a 1Hz square wave
*
* Initialize the RTC RAM for on/off times
* Initialize the on/off times in RTC RAM
* Bits 7-4: Hour (1-12)
* Bits 3-1: Minute (0-5, x10)
* Bit 0: AM/PM
* INIT: 12AM: 1100 000 0 = 0xC0
*/
void clk_init() {
clkRegs[0] = 0x00; //Seconds: 00
clkRegs[1] = 0x00; //Minutes: 00
clkRegs[2] = 0x72; //Hour: 12pm
clkRegs[3] = 0x04; //Day of the week: Wednesday
clkRegs[4] = 0x01; //Date: 01
clkRegs[5] = 0x04; //Month: 04
clkRegs[6] = 0x09; //Year: 2009
clkRegs[7] = 0x10; //outputs 1hz square wave from SQWE pin
void clkRegs_init() {
clkRegs[8] = clkRegs[9] = 0xC0;
clkRegs[10] = clkRegs[11] = clkRegs[12] = clkRegs[13] = clkRegs[14] = clkRegs[15] =
clkRegs[16] = clkRegs[17] = clkRegs[18] = clkRegs[19] = 0xC0;
clkRegs[20] = clkRegs[21] = clkRegs[22] = clkRegs[23] = clkRegs[24] = clkRegs[25] =
clkRegs[26] = clkRegs[27] = clkRegs[28] = clkRegs[29] = 0xC0;
clkRegs[30] = clkRegs[31] = clkRegs[32] = clkRegs[33] = clkRegs[34] = clkRegs[35] =
clkRegs[36] = clkRegs[37] = clkRegs[38] = clkRegs[39] = 0xC0;
clkRegs[40] = clkRegs[41] = clkRegs[42] = clkRegs[43] = clkRegs[44] = clkRegs[45] =
clkRegs[46] = clkRegs[47] = clkRegs[48] = clkRegs[49] = 0xC0;
clkRegs[50] = clkRegs[51] = clkRegs[52] = clkRegs[53] = clkRegs[54] = clkRegs[55] = 0xC0;
}
void clkRAM_init() {
unsigned char clkRAM[56];
clkRAM[0] = clkRAM[1] = clkRAM[2] = clkRAM[3] = clkRAM[4] = clkRAM[5] =
clkRAM[6] = clkRAM[7] = clkRAM[8] = clkRAM[9] = 0xC0;
clkRAM[10] = clkRAM[11] = clkRAM[12] = clkRAM[13] = clkRAM[14] = clkRAM[15] =
clkRAM[16] = clkRAM[17] = clkRAM[18] = clkRAM[19] = 0xC0;
clkRAM[20] = clkRAM[21] = clkRAM[22] = clkRAM[23] = clkRAM[24] = clkRAM[25] =
clkRAM[26] = clkRAM[27] = clkRAM[28] = clkRAM[29] = 0xC0;
clkRAM[30] = clkRAM[31] = clkRAM[32] = clkRAM[33] = clkRAM[34] = clkRAM[35] =
clkRAM[36] = clkRAM[37] = clkRAM[38] = clkRAM[39] = 0xC0;
clkRAM[40] = clkRAM[41] = clkRAM[42] = clkRAM[43] = clkRAM[44] = clkRAM[45] =
clkRAM[46] = clkRAM[47] = clkRAM[48] = clkRAM[49] = 0xC0;
clkRAM[50] = clkRAM[51] = clkRAM[52] = clkRAM[53] = clkRAM[54] = clkRAM[55] =
0xC0;
del1m(1);
i2c_write2(CLOCK_WR_ADDR, clkRAM, 56, 0x08);
//ADDR.Address = reg;
}
MMCR_MMTXAK = 0;
// MCU will ACK received data
MMADR = CLOCK_WR_ADDR;
// Device address -> address reg.
//MMDTR = ADDR.Bytes.Address_H; // High byte of data address
MMDTR = reg; //data address
MIMCR_MMRW = 0;
// Set for transmit
MIMCR_MMAST = 1;
// Initiate transfer
/* i2c_write2 - write bytes to an I2C device (two byte address) */
void i2c_write2(unsigned char device_addr, unsigned char *p, int n, byte reg) {
//ADDR.Address = reg;
// Copy address to struct
while (MIMCR_MMBB);
// Wait for bus not busy
while (!(MMSR_MMTXBE));
// Wait for TX buffer
empty////////////////////////////////STUCK HERE: MMSR_MMTXBE never goes to 1
MMADR = device_addr;
// Device address -> address reg
//MMDTR = ADDR.Bytes.Address_H; // High byte of data address
MMDTR = reg;
MIMCR_MMRW = 0;
// Set for transmit
MIMCR_MMAST = 1;
// Start transmission
//while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
//MMDTR = ADDR.Bytes.Address_L; // Low byte of data address
//while (MMSR_MMRXAK);
// Wait for ACK from slave
//while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
//MMDTR = ADDR.Bytes.Address_L; // Low byte of data address
//while (MMSR_MMRXAK);
// Wait for ACK from slave
while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
MMDTR = 0xff;
// Dummy data to get ACK clock
while (MMSR_MMRXAK);
// Wait for ACK from slave
MMADR = device_addr;
// device address -> address reg.
//MMDTR = 0xff;
// dummy data -> data reg.
MIMCR_MMRW = 1;
// Set for receive
MMCR_REPSEN = 1;
// Enable repeated start
MIMCR_MMAST = 1;
// Initiate transfer
while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
MMDTR = 0xff;
// Dummy data -> data reg
while (MMSR_MMRXAK);
// Wait for ACK from slave
while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
MMDTR = *p++;
// First byte of data to write
while (MMSR_MMRXAK);
// Wait for ACK from slave
while (n > 0) {
n--;
// Decrement count
while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
if (n == 0)
// Is this the last byte?
MMDTR = 0xff;
// Yes. dummy data -> DTR
else
MMDTR = *p++;
// No. next data -> DTR
while (MMSR_MMRXAK);
// Wait for ACK from slave
}
MIMCR_MMAST = 0;
// Generate STOP bit
//MMCR_MMEN = 0;
//MMCR_MMEN = 1;
// Copy address to struct
n--;
// Loop n-1 times before last read
while (n > 0) {
// Up to last byte
while (!(MMSR_MMRXBF));
// Wait for RX buffer full
*p++ = MMDRR;
// Get data
n--;
// Decrement total count
}
MMCR_MMTXAK = 1;
// Don't send ACK for last byte
while (!(MMSR_MMRXBF));
// Wait for RX buffer full
*p++ = MMDRR;
// Get data
MIMCR_MMAST = 0;
// Generate STOP bit
// disable MMIIC
// Enable MMIIC
}
MMCR_MMEN = 0;
MMCR_MMEN = 1;
/* i2c_read2 - read bytes from an I2C device (two byte address) */
void i2c_read2(unsigned char device_addr, unsigned char *p, int n, byte reg) {
unsigned char x;
x = MMDRR;
// This should clear the MMRXBF flag
// disable MMIIC
// Enable MMIIC
}
/**************************************** I2C - Real Time Clock
****************************************/
; A 9.8304MHz external clock gives an internal CPU clock of
; 2.4576MHz (407ns/cycle). 95 x .407 usec = 38.7 usec.
; The JSR and RTS instructions will add a bit more.
mov #13,delay0 ; 4 cycles
u1: dec delay0
; 4 cycles
bne u1
; 3 cycles
/**************************************** SCI Port
****************************************/
/* sci_init - Initialize the SCI port */
void sci_init(void) {
SCC1_ENSCI = 1;
// Enable SCI
/* Set output for 9600 baud. Assumes a 9.8304MHz clock */
SCBR_SCP = 0;
// Baud rate prescaler = 1
SCBR_SCR = 2;
// Baud rate divisor = 4
SCC2_TE = 1;
// Enable transmitter
}
/* sciout - Output a byte to SCI port */
void sciout(unsigned char ch) {
while (SCS1_SCTE == 0);
SCDR = ch;
}
/* sciouts - Print the contents of the character string "s" out the SCI
port. The string must be terminated by a zero byte */
void sciouts(unsigned char *s) {
unsigned char ch;
while ((ch = *s++) != (unsigned char) NULL)
sciout(ch);
}
}
}
/* del1m - Delay about 1msec times the "d" argument */
void del1m(int d) {
while (d--) {
asm {
; The following code delays 1 millisecond by looping.
; Total time is 4 + 5 * (4 + 68 * (4 + 3) + 4 + 3) = 2439 cycles
; A 9.8304MHz external clock gives an internal CPU clock of
; 2.4576MHz (407ns/cycle). Delay is then .993 milliseconds.
mov #$5,delay1 ; 4 cycles
m1: mov #68,delay0 ; 4 cycles
m0: dec delay0
; 4 cycles
bne m0
; 3 cycles
dec delay1
; 4 cycles
bne m1
; 3 cycles
}
}
}
}
/**************************************** SCI Port
****************************************/
/**************************************** DELAY
****************************************/
/**************************************** TEST
****************************************/
/***************************************** DELAY
****************************************/
/* Note: these delay routines only work if the the delay0 and delay1
variables are located in the RAM zero page */
/* del40u - Delay about 40usec times the "d" argument */
void del40u(int d) {
while (d--) {
asm {
; The following code delays about 40 microseconds by looping.
; Total time is 4 + 13 * (4 + 3) = 95 cycles
void LCDMenu() {
del1m(100);
clearLCD();
while(one) {
if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
progMenuTime();
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
progMenuOutlets();
} //end if LEFT
else { //DISPLAY TIME
del1m(2);
strout(LCD_LINE1, (unsigned char *) strdurasaver);
del1m(2);
testCLK();
del1m(995);
}
clearLCD();
//cmdout(0x02); //cursor home
strout(LCD_LINE1, (unsigned char *) rightstr); // "you pressed right!"
strout(LCD_LINE2, (unsigned char *) str3); //"Dare to press another?"
} else if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
clearLCD();
//cmdout(0x02); //cursor home
strout(LCD_LINE1, (unsigned char *) upstr); // "you pressed up!"
strout(LCD_LINE2, (unsigned char *) str3); //"Dare to press another?"
} else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
clearLCD();
//cmdout(0x02); //cursor home
strout(LCD_LINE1, (unsigned char *) downstr); // "you pressed down!"
strout(LCD_LINE2, (unsigned char *) str3); //"Dare to press another?"
} else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
clearLCD();
//cmdout(0x02); //cursor home
strout(LCD_LINE1, (unsigned char *) selectstr); // "you pressed select!"
strout(LCD_LINE2, (unsigned char *) str3); //"Dare to press another?"
} else { // do nothing
}
}
}
void testRemote() {
while(one) {
clearLCD();
if(checkManualOverride() == 1) {
strout(0, "manual override 1");
if(outlet[0] == 1) {
outlet[0] = 0;
OUTLET1 = 0;
strout(LCD_LINE2, "turn off");
del1m(thousand);
}
else if(outlet[0] == 0) {
outlet[0] = 1;
OUTLET1 = 1;
strout(LCD_LINE2, "turn on");
del1m(thousand);
}
}
}
}
/* Displays confirmation on the LCD of which button is pressed */
void testButtonsLCD() {
while(one) {
while(!LEFT && !RIGHT && !UP && !DOWN && !SELECT) testCLK();
if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
clearLCD();
//cmdout(0x02); //cursor home
strout(LCD_LINE1, (unsigned char *) leftstr); // "you pressed left!"
strout(LCD_LINE2, (unsigned char *) str3); //"Dare to press another?"
} else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
}
}
/* This program will test button function, output to an LED.
*
* LED: PTA0, output
* Left Button: LED blink 5x
* Right Button: LED blink 4x
* Up Button: LED blink 3x
* Down Button: LED blink 2x
* Select Button: LED blink 1x
*/
void testButtonsLED() {
PTA_PTA0 = 1; //LED off to start
while (1) { // Loop forever
if (LEFT) { //--> blink 5x
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
}
else if(RIGHT) { //--> blink 4x
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
}
else if(UP) { // --> blink 3x
if(swDebounce) while(UP) {} //debounce - wait until button is released
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
}
else if(DOWN) { //--> blink 2x
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
}
else if(SELECT) { //--> blink 1x
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
blink(thousand);
del1m(thousand);
}
else
PTA_PTA0 = 1; //off
}
}
strout(0x40, "Sunday");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, stroffhour);
del1m(2);
strout(0x40, "08AM");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, stroffmin);
del1m(2);
strout(0x40, "08:30AM");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, stronhour);
del1m(2);
strout(0x40, "05PM");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
void testI2Crap() {
//testCLK(); //do a read
strout(0, "before 2nd clkinit");
del1m(thousand);
clk_init();
strout(0, "woot woot");
//while(one) {
//testCLK();
//del1m(thousand);
//}
del1m(thousand);
programCLK();
}
void fakeLCD() {
unsigned char repeat = 1;
while(repeat) {
del1m(2);
strout(0, stroutlet);
del1m(2);
strout(0x40, "Outlet 1");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, stroutlet);
del1m(2);
strout(0x40, strexit);
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, strprogday);
del1m(2);
strout(0, stronmin);
del1m(2);
strout(0x40, "05:20PM");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
}
void testCLKRegs(void) {
unsigned char teststr[24];
unsigned char offset, i, temp, outletNum, today, regOffset, addrOffset;
today = 1;
outletNum = 1;
clkRegs[8] = 0x88;
clkRegs[9] = 0x77;
clkRegs[10] = 0x66;
clkRegs[11] = 0x55;
clkRegs[12] = 0x44;
clkRegs[13] = 0x33;
clkRegs[14] = 0x22;
clkRegs[15] = 0x11;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[8], 1, 0x08);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[9], 1, 0x09);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[10], 1, 0x0A);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[11], 1, 0x0B);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[12], 1, 0x0C);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[13], 1, 0x0D);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[14], 1, 0x0E);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[15], 1, 0x0F);
del1m(1);
getDevData(1);
teststr[0] = off10hr[0];
teststr[1] = off09hr[0];
teststr[2] = ':';
teststr[3] = offmin[0];
teststr[4] = '0';
teststr[5] = onpm[0];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[0];
teststr[9] = on09hr[0];
teststr[10] = ':';
teststr[11] = onmin[0];
teststr[12] = '0';
teststr[13] = onpm[0];
teststr[14] = 'M';
teststr[15] = '\0';
strout(0, teststr);
today = 1;
outletNum = 1;
regOffset = (outletNum - 1) * 2;
addrOffset = (regOffset >> 4) & 0x0f;
off10hr[0] = '0';
off09hr[0] = '9';
offpm[0] = '0';
offmin[0] = '0';
on10hr[0] = '0';
on09hr[0] = '6';
onpm[0] = '1';
onmin[0] = '3';
temp = ((((off10hr[outletNum - 1]*10) + off09hr[outletNum - 1]) & 0x0f) << 4) |
(((offmin[outletNum - 1] & 0x07) << 1) | (offpm[outletNum - 1] & 0x01)); //1001 0000 = 0x90
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset], 1,
SUNSTART + addrOffset);
break;
case '2': //Monday
clkRegs[MONREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset],
1, MONSTART + addrOffset);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset], 1,
TUESTART + addrOffset);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset],
1, WEDSTART + addrOffset);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset +
1], 1, FRISTART + addrOffset + 0x01);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset +
1], 1, SATSTART + addrOffset + 0x01);
break;
} //end switch(today)
del1m(1);
getDevData(1);
teststr[0] = off10hr[0];
teststr[1] = off09hr[0];
teststr[2] = ':';
teststr[3] = offmin[0];
teststr[4] = '0';
teststr[5] = onpm[0];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[0];
teststr[9] = on09hr[0];
teststr[10] = ':';
teststr[11] = onmin[0];
teststr[12] = '0';
teststr[13] = onpm[0];
teststr[14] = 'M';
teststr[15] = '\0';
strout(0x40, teststr);
del1m(5000);
clearLCD();
strout(0, teststr);
off10hr[0] = '1';
off09hr[0] = '2';
offpm[0] = '1';
offmin[0] = '2';
on10hr[0] = '1';
on09hr[0] = '0';
onpm[0] = '0';
break;
case '5': //Thursday
clkRegs[THUREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset],
1, THUSTART + addrOffset);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset], 1,
FRISTART + addrOffset);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset], 1,
SATSTART + addrOffset);
break;
} //end switch(today)
temp = ((((on10hr[outletNum - 1]*10) + on09hr[outletNum - 1]) & 0x0f) << 4) |
(((onmin[outletNum - 1] & 0x07) << 1) | (onpm[outletNum - 1] & 0x01)); //0110 0110 = 0x66
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset +
1], 1, SUNSTART + addrOffset + 0x01);
break;
case '2': //Monday
clkRegs[MONREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset +
1], 1, MONSTART + addrOffset + 0x01);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset +
1], 1, TUESTART + addrOffset + 0x01);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset +
1], 1, WEDSTART + addrOffset + 0x01);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset +
1], 1, THUSTART + addrOffset + 0x01);
onmin[0] = '4';
temp = ((((off10hr[outletNum - 1]*10) + off09hr[outletNum - 1]) & 0x0f) << 4) |
(((offmin[outletNum - 1] & 0x07) << 1) | (offpm[outletNum - 1] & 0x01)); //1001 0000 = 0x90
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset], 1,
SUNSTART + addrOffset);
break;
case '2': //Monday
clkRegs[MONREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset],
1, MONSTART + addrOffset);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset], 1,
TUESTART + addrOffset);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset],
1, WEDSTART + addrOffset);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset],
1, THUSTART + addrOffset);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset], 1,
FRISTART + addrOffset);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset], 1,
SATSTART + addrOffset);
break;
} //end switch(today)
temp = ((((on10hr[outletNum - 1]*10) + on09hr[outletNum - 1]) & 0x0f) << 4) |
(((onmin[outletNum - 1] & 0x07) << 1) | (onpm[outletNum - 1] & 0x01)); //0110 0110 = 0x66
teststr[4] = '0';
teststr[5] = onpm[0];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[0];
teststr[9] = on09hr[0];
teststr[10] = ':';
teststr[11] = onmin[0];
teststr[12] = '0';
teststr[13] = onpm[0];
teststr[14] = 'M';
teststr[15] = '\0';
strout(0x40, teststr);
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset +
1], 1, SUNSTART + addrOffset + 0x01);
break;
case '2': //Monday
clkRegs[MONREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset +
1], 1, MONSTART + addrOffset + 0x01);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset +
1], 1, TUESTART + addrOffset + 0x01);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset +
1], 1, WEDSTART + addrOffset + 0x01);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset +
1], 1, THUSTART + addrOffset + 0x01);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset +
1], 1, FRISTART + addrOffset + 0x01);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset +
1], 1, SATSTART + addrOffset + 0x01);
break;
} //end switch(today)
del1m(5000);
del1m(1);
//i2c_read2(CLOCK_RD_ADDR, dayData, 8, 0x08);
getDevData(1);
teststr[0] = hexCode[(dayData[0] >> 4) & 0x0f];
teststr[1] = hexCode[(dayData[0]) & 0x0f];
teststr[2] = hexCode[(dayData[1] >> 4) & 0x0f];
teststr[3] = hexCode[(dayData[1]) & 0x0f];
teststr[4] = hexCode[(dayData[2] >> 4) & 0x0f];
teststr[5] = hexCode[(dayData[2]) & 0x0f];
teststr[6] = hexCode[(dayData[3] >> 4) & 0x0f];
teststr[7] = hexCode[(dayData[3]) & 0x0f];
teststr[8] = hexCode[(dayData[4] >> 4) & 0x0f];
teststr[9] = hexCode[(dayData[4]) & 0x0f];
teststr[10] = hexCode[(dayData[5] >> 4) & 0x0f];
teststr[11] = hexCode[(dayData[5]) & 0x0f];
teststr[12] = hexCode[(dayData[6] >> 4) & 0x0f];
teststr[13] = hexCode[(dayData[6]) & 0x0f];
teststr[14] = hexCode[(dayData[7] >> 4) & 0x0f];
teststr[15] = hexCode[(dayData[7]) & 0x0f];
teststr[16] = '\0';
//strout(0, teststr);
del1m(1);
getDevData(1);
teststr[0] = off10hr[0];
teststr[1] = off09hr[0];
teststr[2] = ':';
teststr[3] = offmin[0];
//clkRegs[8] = 0xA4; //0001 001 0 = 1:10am, 1010 010 0 = A4 = 10:20am
//clkRegs[9] = 0xC9; //0010 010 1 = 2:20pm, 1100 100 1 = C9 = 12:40pm
//i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[8], 1, 0x08);
//i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[9], 1, 0x09);
onmin[i-1] = hexCode[(dayData[offset+1] & 0x0e) >> 1]; //all but last bit (bits 3-1)
if(hexCode[(dayData[offset+1] & 0x01)] == '0') //last bit is am/pm
onpm[i-1] = 'A';
else if(hexCode[(dayData[offset+1] & 0x01)] == '1')
onpm[i-1] = 'P';
else
onpm[i-1] = '?';
del1m(1);
//i2c_read2(CLOCK_RD_ADDR, dayData, 8, SUNSTART);
getDevData(1);
i = 1;
offset = (i - 1) * 2; //index offset for dayData, based on device #
//e.g. dev 4 is stored at 6 and 7 (4 - 1 = 3 * 2 = 6)
// (2a) process "off" time
if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'A') {
off10hr[i-1] = '1';
off09hr[i-1] = '0';
} else if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'B') {
off10hr[i-1] = '1';
off09hr[i-1] = '1';
} else if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'C') {
off10hr[i-1] = '1';
off09hr[i-1] = '2';
} else {
off10hr[i-1] = '0';
off09hr[i-1] = hexCode[(dayData[offset] >> 4) & 0x0f]; //up to 9
}
offmin[i-1] = hexCode[(dayData[offset] & 0x0e) >> 1]; //all but last bit (bits 3-1)
if(hexCode[(dayData[offset] & 0x01)] == '0') //last bit is am/pm
offpm[i-1] = 'A';
else if(hexCode[(dayData[offset] & 0x01)] == '1')
offpm[i-1] = 'P';
else
offpm[i-1] = '?';
// (2b) process "on" time
if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'A') {
on10hr[i-1] = '1';
on09hr[i-1] = '0';
} else if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'B') {
on10hr[i-1] = '1';
on09hr[i-1] = '1';
} else if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'C') {
on10hr[i-1] = '1';
on09hr[i-1] = '2';
} else {
on10hr[i-1] = '0';
on09hr[i-1] = hexCode[(dayData[offset+1] >> 4) & 0x0f]; //up to 9
}
teststr[0] = off10hr[0];
teststr[1] = off09hr[0];
teststr[2] = ':';
teststr[3] = offmin[0];
teststr[4] = '0';
teststr[5] = onpm[0];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[0];
teststr[9] = on09hr[0];
teststr[10] = ':';
teststr[11] = onmin[0];
teststr[12] = '0';
teststr[13] = onpm[0];
teststr[14] = 'M';
teststr[15] = '\0';
//strout(0x40, teststr);
//del1m(5000);
}
void testOutlets() {
del1m(2);
DDRB_DDRB0 = 1;
DDRB_DDRB1 = 1;
DDRB_DDRB2 = 1;
DDRB_DDRB3 = 1;
while(one) {
OUTLET1 = 1;
strout(0, "outlet 1");
del1m(thousand);
OUTLET1 = 0;
OUTLET2 = 1;
strout(0, "outlet 2");
del1m(thousand);
OUTLET2 = 0;
OUTLET3 = 1;
strout(0, "outlet 3");
del1m(thousand);
OUTLET3 = 0;
OUTLET4 = 1;
strout(0, "outlet 4");
del1m(thousand);
OUTLET4 = 0;
}
}
/* turn on LED in port A bit 0 for n msec, then turn off */
void blink(int n) {
PTA_PTA0 = 0; //turn on LED
del1m(n); //leave on n msec
PTA_PTA0 = 1; //turn off LED
}
/* test manual override */
void testManOv() {
while(one) {
switch(checkManualOverride()) {
case 1:
blink(1000);
if(outlet[0] == 1) {
outlet[0] = OUTLET1 = 0;
}
else if(outlet[0] == 0) {
outlet[0] = OUTLET1 = 1;
}
strout(0, "manov 1!");
break;
case 2:
blink(1000);
blink(1000);
if(outlet[1] == 1) {
outlet[1] = OUTLET2 = 0;
/*********************************************************************
* EE 459 Spring 2009 Team 1 - Duracell
* Sara Adkins
* Paul VanWieren
* Robert Whitley
*********************************************************************/
#include <stdio.h>
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include <string.h>
/* The following puts the dummy interrupt service routine at
location MY_ISR_ROM which is defined in the PRM file as
the start of the FLASH ROM */
#pragma CODE_SEG MY_ISR_ROM
#pragma TRAP_PROC
void dummyISR(void) { }
/* This prag sets the code storage back to default area of ROM
as defined in the PRM file */
#pragma CODE_SEG DEFAULT
/*
*
Port D, bit 1 (0x02) - output to RS (Register Select) input of display
*
bit 2 (0x04) - output to R/W (Read/Write) input of display
*
bit 3 (0x08) - output to E (Enable) input of display
*
Port B, bits 4-7 - Outputs to DB4-DB7 inputs of display.
*
*
The second line of the display starts at address 0x40.
*
* ---Storage of On/Off times on RTC:--* Bits 7-4: Hour (1-12)
* Bits 3-1: Minute (0-5, x10)
* Bit 0: AM/PM
* x2 times per device x7 days x4 devices = 56 bytes (total RAM!)
*
* Device 1: reg 0x08 - 0x15
* Device 2: reg 0x16 - 0x23
}
else if(outlet[1] == 0) {
outlet[1] = OUTLET2 = 1;
}
strout(0, "manov 2!");
break;
case 3:
blink(1000);
blink(1000);
blink(1000);
if(outlet[2] == 1) {
outlet[2] = OUTLET3 = 0;
}
else if(outlet[2] == 0) {
outlet[2] = OUTLET3 = 1;
}
strout(0, "manov 3!");
break;
case 4:
blink(1000);
blink(1000);
blink(1000);
blink(1000);
if(outlet[3] == 1) {
outlet[3] = OUTLET4 = 0;
}
else if(outlet[3] == 0) {
outlet[3] = OUTLET4 = 1;
}
strout(0, "manov 4!");
break;
default:
del1m(2);
strout(0, strdurasaver);
testCLK();
del1m(1000);
} //end switch
} //end while(one)
}
/**************************************** TEST
****************************************/
Source Code for Remote Control
* Device 3: reg 0x24 - 0x31
* Device 4: reg 0x32 - 0x3F
*/
/* The NIBBLE_HIGH condition determines whether PTB bits 4-7 or 0-3 are used
to send the four bit nibble to the LCD.
If NIBBLE_HIGH is declared, use PTB 4-7.
If NIBBLE_HIGH not declared, use PTB 0-3. */
#define NIBBLE_HIGH // Use bits 4-7 for talking to LCD
/* function declarations */
void initializeLCD(void);
void clearLCD(void);
void strout(int, unsigned char *);
void iniout(unsigned char);
void cmdout(unsigned char);
void datout(unsigned char);
void nibout(unsigned char);
void busywt(void);
void del40u(int);
void del1m(int);
void sci_init(void);
void i2c_init(unsigned char);
void i2c_write2(unsigned char, unsigned char *, int, unsigned char);
void i2c_read2(unsigned char, unsigned char *, int, unsigned char);
void clk_init(void);
void clkRAM_init(void);
void clkRegs_init(void);
void blink(int);
void manualOn(void);
void manualOff(void);
unsigned char checkManualOverride(void);
unsigned char check_offtime(unsigned char);
unsigned char check_ontime(unsigned char);
unsigned int qualifyTime(unsigned char, unsigned char);
void testCLK(void);
void getTime(void);
void getDevData(unsigned char);
void programCLK(void);
void programOutlet(unsigned char);
void programDEV(void);
void progMenuTime(void);
void progMenuOutlets(void);
void LCD_Time(void);
void LCDMenu(void);
void mainLoop(void);
void dummyMain(void);
//TEST//
void testOutlets(void);
void fakeLCD(void);
void testButtonsLED(void);
void testButtonsLCD(void);
void testI2Crap(void);
void testCLKRegs(void);
void testOutlets(void);
void testRemote(void);
//TEST//
/* button input ports */
#define LEFT PTA_PTA1
#define RIGHT PTD_PTD6
#define UP PTD_PTD5
#define DOWN PTD_PTD4
#define SELECT PTD_PTD0
#define THUREG 40
#define FRIREG 48
#define SATREG 56
#define TOTALDEVS 4 //4 devices/outlets total
/* This pragma sets the area for allocating variables to the zero page
of RAM (0x00 to 0xff) for more efficient access.*/
#pragma DATA_SEG __SHORT_SEG MY_ZEROPAGE
unsigned char delay0;
unsigned char delay1;
unsigned char delay2;
/* This pragma sets the area for allocating variables back to the default area
of RAM as defined in the PRM file. */
#pragma DATA_SEG DEFAULT
/* outlet output ports */
#define OUTLET1 PTB_PTB0
#define OUTLET2 PTB_PTB1
#define OUTLET3 PTB_PTB2
#define OUTLET4 PTB_PTB3
/* LCD */
#define LCD_LINE1 0
#define LCD_LINE2 0x40
/* Addresses for the clock on the I2C bus */
#define CLOCK_WR_ADDR 0xD0 /* clock write address */
#define CLOCK_RD_ADDR 0xD1 /* clock read address */
/* clk reg organized by day of the week */
#define SUNSTART 0x08 //for i2c read/write
#define MONSTART 0x10
#define TUESTART 0x18
#define WEDSTART 0x20
#define THUSTART 0x28
#define FRISTART 0x30
#define SATSTART 0x38
#define SUNREG 8 //for clkRegs[]
#define MONREG 16
#define TUEREG 24
#define WEDREG 32
const unsigned char stroffhour[] = "Select Off Hour";
const unsigned char stroffmin[] = "Select Off Minute";
const unsigned char stronhour[] = "Select On Hour";
const unsigned char stronmin[] = "Select On Minute";
const unsigned char strweekday[] = "Set Day of the Week";
const unsigned char strsun[] = "Sunday ";
const unsigned char strmon[] = "Monday ";
const unsigned char strtue[] = "Tuesday ";
const unsigned char strwed[] = "Wednesday";
const unsigned char strthu[] = "Thursday ";
const unsigned char strfri[] = "Friday ";
const unsigned char strsat[] = "Saturday ";
const unsigned char strmonth[] = "Set Month";
const unsigned char strjan[] = "January ";
const unsigned char strfeb[] = "February ";
const unsigned char strmar[] = "March ";
const unsigned char strapr[] = "April ";
const unsigned char strmay[] = "May ";
const unsigned char strjun[] = "June ";
const unsigned char strjul[] = "July ";
const unsigned char straug[] = "August ";
const unsigned char strsep[] = "September";
const unsigned char stroct[] = "October ";
const unsigned char strnov[] = "November ";
const unsigned char strdec[] = "December ";
const unsigned char strdate[] = "Set Date (01-31)";
const unsigned char stryear[] = "Set Year (2000-2099)";
const unsigned char strtimehr[] = "Set Hour (01-12 AM/PM)";
const unsigned char strtimemin[] = "Set Minute (00-59)";
const unsigned char strmanon[] = "Manual Override On";
const unsigned char strmanoff[] = "Manual Override Off";
const unsigned char strohnoes[] = "???";
const unsigned char hexCode[] = "0123456789ABCDEF";
const unsigned char one = 1;
const unsigned char zero = 0;
const unsigned int thousand = 1000;
const unsigned char keeppw = 0xF0;
const unsigned char keepcode = 0x0F;
const unsigned char password = 0xD0;
const unsigned char code0 = 0x00;
const unsigned char code1 = 0x01;
const unsigned char code2 = 0x02;
const unsigned char code3 = 0x03;
/* Declare these strings as "const" so they are allocated in ROM */
//TEST//
#ifdef NIBBLE_HIGH
const unsigned char str1[] = "Hi! Press a button";
#else
const unsigned char str1[] = "'lo! Press a button";
#endif
const unsigned char str2[] = "...if you DARE";
const unsigned char str3[] = "Dare to press another?";
const unsigned char upstr[] = "you pressed UP!";
const unsigned char downstr[] = "you pressed DOWN!";
const unsigned char leftstr[] = "you pressed LEFT!";
const unsigned char rightstr[] = "you pressed RIGHT!";
const unsigned char selectstr[] = "you pressed SELECT!";
//TEST//
const unsigned char clearstr[] = "
";
const unsigned char strdurasaver[] = "Duracell DuraSaver
";
const unsigned char strprogmenu[] = "Programming Menu";
const unsigned char strprogdev[] = "Program Devices";
const unsigned char strsetclk[] = "Set Clock & Date";
const unsigned char strexit[] = "Exit ";
const unsigned char stroutlet[] = "Select Outlet";
const unsigned char strprogday[] = "Select Day of the Week";
const unsigned char swDebounce = 1; //1 for software debounce, 0 for hardware only
unsigned char PWCODE;
unsigned char PW;
unsigned char CODE;
unsigned char today; //this is for LCD menu; actual current day of the week is stored in
dayofweek (against all common sense, I know)
unsigned char timesToday; //keeps track of which day of the week's on/off times are stored in the
off/on[] variables
unsigned char seconds10, seconds09, minutes10, minutes09, hours10, hours09, pm,
dayofweek, date10, date09, months10, months09, years10, years09; //time right now get from clock
unsigned char off10hr[TOTALDEVS], off09hr[TOTALDEVS], offmin[TOTALDEVS],
offpm[TOTALDEVS], //programmed "off" times, 1 per each of 4 devices
on10hr[TOTALDEVS], on09hr[TOTALDEVS], onmin[TOTALDEVS],
onpm[TOTALDEVS];
//programmed "on" times, 1 per each of 4 devices
/* manual override - 0 is off, 1 is on (default is off) */
unsigned char manual[TOTALDEVS];
/* outlets - 0 is off, 1 is on (default is on) */
unsigned char outlet[TOTALDEVS];
unsigned char time[24]; //Day, MO/DD/YR HH:MM xm
unsigned char teststr[24]; //to print test statements, variables
unsigned char clkRegs[64];
unsigned char dayData[8];
/****************** MAIN ******************/
void main(void) {
// EnableInterrupts; /* enable interrupts */
/* include your code here */
CONFIG1_COPD = 1;
CONFIG2_IICSEL = 1;
// disable COP reset
// IIC on PTA2, 3
DDRA_DDRA0 = 1;
DDRD_DDRD0 = 0;
DDRD_DDRD4 = 0;
DDRD_DDRD5 = 0;
DDRD_DDRD6 = 0;
DDRA_DDRA1 = 0;
// Set PTA0 = 1 for output (LED)
// clear PTD0 = 0 for input (SELECT button)
// clear PTD4 = 0 for input (DOWN button)
// clear PTD5 = 0 for input (UP button)
// clear PTD6 = 0 for input (RIGHT button)
// clear PTA1 = 0 for input (LEFT button)
PTA_PTA0 = 1;
/* global variables */
//LED off
/* Set baud rate to 38,400. Clock = 9.8304MHz. Divisor = 64. */
i2c_init((unsigned char) 3); // Initialize the IIC port
sci_init();
// Initialize the SCI port
#ifdef NIBBLE_HIGH
DDRB = 0xf0;
#else
DDRB = 0x0f;
#endif
DDRD = 0x0e;
void dummyMain() {
del1m(thousand);
clearLCD();
del1m(thousand);
mainLoop();
}
// Set PTB bits 4-7 for output
// Set PTB bits 0-3 for output
void mainLoop() {
unsigned char outletNum = TOTALDEVS;
// Set PTD1, 2, and 3 for output
initializeLCD();
// Initialize the LCD display
//ONLY ONCE//clk_init(); // Initialize the Clock (ONLY HAS TO BE DONE ONCE)
//clkRAM_init(); //initialize the clkRegs + initalize the clock RAM (other than time & date)
clkRegs_init(); //initialize the clkRegs
del1m(thousand);
DDRB_DDRB0 = 1;
// Set PTB0 = 1 for output (Outlet 1)
DDRB_DDRB1 = 1;
// Set PTB1 = 1 for output (Outlet 2)
DDRB_DDRB2 = 1;
// Set PTB2 = 1 for output (Outlet 3)
DDRB_DDRB3 = 1;
// Set PTB3 = 1 for output (Outlet 4)
outlet[0] = 1;
OUTLET1 = 1; //Outlet 1 on by default
outlet[1] = 1;
OUTLET2 = 1; //Outlet 2 on by default
outlet[2] = 1;
OUTLET3 = 1; //Outlet 3 on by default
outlet[3] = 1;
OUTLET4 = 1; //Outlet 4 on by default
del1m(thousand);
timesToday = dayofweek;
/* main loop */
while(one) {
dummyMain();
}
/* please make sure that you never leave this function */
}
/********************************************* MAIN LCD MENU
*********************************************/
// check for RF remote manual override request
if(checkManualOverride() == outletNum) {
// check for manual override (off --> on)
if(manual[outletNum-1] == 0) { //if manual override currently off
manual[outletNum-1] = 1;
if(outlet[outletNum-1] == 1) { //outlet 1 is on --> turn it off
outlet[outletNum-1] = 0;
switch(outletNum) {
case 1:
OUTLET1 = 0;
break;
case 2:
OUTLET2 = 0;
break;
case 3:
OUTLET3 = 0;
break;
case 4:
OUTLET4 = 0;
break;
} //end switch
//strout(LCD_LINE1, "manv off!");
//del1m(thousand);
}
else { //outlet 1 is off --> turn it on
outlet[outletNum-1] = 1;
switch(outletNum) {
case 1:
OUTLET1 = 1;
break;
case 2:
OUTLET2 = 1;
break;
case 3:
OUTLET3 = 1;
break;
case 4:
OUTLET4 = 1;
break;
} //end switch
//strout(LCD_LINE1, "manv on !");
//del1m(thousand);
}
} //end if manual override currently off
// check for manual override (on --> off)
else if(manual[outletNum-1] == 1) {
strout(LCD_LINE1, (unsigned char *) strdurasaver);
testCLK();
while(one) {
del1m(thousand);
clearLCD();
getTime(); //update time variables
// check for RIGHT button press --> program clock
if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
progMenuTime();
}
// check for LEFT button press --> program outlets
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
progMenuOutlets();
}
//check for UP button press --> turn on manual override
else if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
manualOn();
}
//check for DOWN button press --> turn off manual override
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
manualOff();
}
for(outletNum = TOTALDEVS; outletNum > 0; outletNum--) { //for each device
manual[outletNum-1] = 0;
} //end if manual override currently on
}
// check if need to turn off outlet
if(outlet[outletNum-1] == 1) {
if(manual[outletNum-1] == 0) {
if(check_offtime(outletNum) == 1) {
outlet[outletNum-1] = 0;
//OUTLET1 = 0; //OFF
switch(outletNum) {
case 1:
OUTLET1 = 0; //off
break;
case 2:
OUTLET2 = 0; //off
break;
case 3:
OUTLET3 = 0; //off
break;
case 4:
OUTLET4 = 0; //off
break;
} //end switch
//strout(LCD_LINE1, "time off!");
//del1m(thousand);
}
}
}
// check if need to turn on outlet
else if(outlet[outletNum-1] == 0) {
if(manual[outletNum-1] == 0) {
if(check_ontime(outletNum) == 1) {
outlet[outletNum-1] = 1;
//OUTLET1 = 1; //ON
switch(outletNum) {
case 1:
OUTLET1 = 1; //on
break;
case 2:
OUTLET2 = 1; //on
break;
case 3:
OUTLET3 = 1; //on
break;
case 4:
OUTLET4 = 1; //on
break;
} //end switch
//strout(LCD_LINE1, "time on !");
//del1m(thousand);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 1");
break;
case 2:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 2");
break;
case 3:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 3");
break;
case 4:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 4");
break;
default:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet ?");
break;
} //end switch
}
}
}
else { //idle --> display time and date
//testCLK();
LCD_Time();
} //end idle
} //end for each device
} //end while(one)
}
void LCD_Time() {
//getTime();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strdurasaver);
del1m(2);
testCLK();
//del1m(500);
}
void manualOn() {
unsigned char choice = 0; //0 = exit
unsigned char repeat = 1;
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
//choice = (choice + 1) % 5;
if(choice == 4)
choice = 0;
else
choice++;
} //end if UP
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
while(repeat) {
switch(choice) {
case 0:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanon);
del1m(2);
strout(LCD_LINE2, (unsigned char *) strexit);
break;
case 1:
del1m(2);
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
//choice = (choice - 1) % 5;
if(choice == 0)
choice = 4;
else
choice--;
} //end if DOWN
strout(LCD_LINE2, "confirmed - another?");
del1m(500);
clearLCD();
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
}//end if choice != 0
if(choice != 0) {
manual[choice - 1] = 1; //turn on manual override
if(outlet[choice - 1] == 1) { //outlet is on --> turn it off
outlet[choice - 1] = 0;
switch(choice) {
case 1:
OUTLET1 = 0; //OFF
break;
case 2:
OUTLET2 = 0; //OFF
break;
case 3:
OUTLET3 = 0; //OFF
break;
case 4:
OUTLET4 = 0; //OFF
break;
} //end switch
//strout(LCD_LINE1, "manv off!");
//del1m(thousand);
} //end if outlet is on --> off
else if(outlet[choice - 1] == 0) { //outlet is off --> turn it on
outlet[choice - 1] = 1;
switch(choice) {
case 1:
OUTLET1 = 1; //ON
break;
case 2:
OUTLET2 = 1; //ON
break;
case 3:
OUTLET3 = 1; //ON
break;
case 4:
OUTLET4 = 1; //ON
break;
} //end switch
//strout(LCD_LINE1, "manv on !");
//del1m(thousand);
} //end if outlet off --> on
else if(choice == 0) {
repeat = '0';
break;
}
} //end if SELECT
} //end repeat
}
void manualOff() {
unsigned char choice = 0; //0 = exit
unsigned char repeat = 1;
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
while(repeat) {
switch(choice) {
case 0:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) strexit);
break;
case 1:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 1");
break;
case 2:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 2");
break;
case 3:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 3");
break;
case 4:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 4");
break;
default:
del1m(2);
strout(LCD_LINE1, (unsigned char *) strmanoff);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet ?");
break;
} //end switch
break;
}
} //end if SELECT
} //end repeat
}
unsigned int qualifyTime(unsigned char outletNum, unsigned char ontime) {
unsigned int qualval, q10hr, q09hr, q10min, q09min, qpm;
getTime(); //update time variables
getDevData(dayofweek); //update on/off times for current day
if(outletNum == 0) { //NOW
q10hr = hours10 & 0x01;
q09hr = hours09 & 0x0f;
q10min = minutes10 & 0x07;
q09min = minutes09 & 0x0f;
qpm = pm & 0x01;
}
else if((outletNum != 0) && (ontime == 1)) {
q10hr = on10hr[outletNum-1] & 0x01;
q09hr = on09hr[outletNum-1] & 0x0f;
q10min = onmin[outletNum-1] & 0x07;
q09min = 0;
qpm = onpm[outletNum-1] & 0x01;
}
else {
q10hr = off10hr[outletNum-1] & 0x01;
q09hr = off09hr[outletNum-1] & 0x0f;
q10min = offmin[outletNum-1] & 0x07;
q09min = 0;
qpm = offpm[outletNum-1] & 0x01;
}
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
//choice = (choice + 1) % 5;
if(choice == 4)
choice = 0;
else
choice++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
//choice = (choice - 1) % 5;
if(choice == 0)
choice = 4;
else
choice--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
if((q10hr == 1) && (q09hr == 2)) { //12xm is always < anything else xm
//qualval = (q10hr * 0) + (q09hr * 0) + (q10min * 10) + (q09min * 1) + (qpm * 1200);
qualval = (q10min * 10) + (q09min) + (qpm * 1200);
}
else {
//qualval = (q10hr * 1000) + (q09hr * 100) + (q10min * 10) + (q09min * 1) + (qpm * 1200);
qualval = (q10hr * 1000) + (q09hr * 100) + (q10min * 10) + (q09min) + (qpm * 1200);
}
return qualval;
if(choice != 0) {
manual[choice - 1] = 0; //turn on manual override
strout(LCD_LINE2, "confirmed - another?");
del1m(500);
clearLCD();
}//end if choice != 0
}
else if(choice == 0) {
repeat = '0';
/* Check Off Time
* This function checks if the given outlet
* is scheduled to be off right now
*/
unsigned char check_offtime(unsigned char outletNum){
unsigned int qON, qOFF, qNOW;
qON = qualifyTime(outletNum, 1);
qOFF = qualifyTime(outletNum, 0);
qNOW = qualifyTime(0, 1);
//strout(LCD_LINE1, "qON == qOFF");
//del1m(thousand);
return 1;
}
if(qOFF < qON) { //turn off then turn on (usually on)
if((qNOW < qOFF) || (qNOW >= qON)) { //time now is before off-time or after on-time
//strout(LCD_LINE1, "outside off-time");
//del1m(thousand);
return 1;
}
}
if(qON == qOFF) { //off and on times are the same --> default ON
//strout(LCD_LINE1, "qOFF == qON");
//del1m(thousand);
return 0;
}
if(qOFF < qON) { //turn off then turn on (usually on)
if((qNOW >= qOFF) && (qNOW < qON)) { //time now is after off-time but before on-time
//strout(LCD_LINE1, "btwn off & on");
//del1m(thousand);
return 1;
}
}
if(qON < qOFF) { //turn on then turn off (usually off)
if((qNOW < qON) || (qNOW >= qOFF)) { //time now is before on-time or after off-time
//strout(LCD_LINE1, "outside on-time");
//del1m(thousand);
return 1;
}
}
return 0;
}
/* Check On Time
* This function checks if the given outlet
* is scheduled to be on right now
*/
unsigned char check_ontime(unsigned char outletNum){
unsigned int qON, qOFF, qNOW;
qON = qualifyTime(outletNum, 1);
qOFF = qualifyTime(outletNum, 0);
qNOW = qualifyTime(0, 1);
if(qON == qOFF) { //off and on times are the same --> default ON
if(qON < qOFF) { //turn on then turn off (usually off)
if((qNOW >= qON) && (qNOW < qOFF)) { //time now is after on-time but before off-time
//strout(LCD_LINE1, "btwn off and on");
//del1m(thousand);
return 1;
}
}
return '0';
}
/* Check for Manual Override
* Returns Outlet Number of Outlet Toggling Manual Override
* Returns 0 if no Outlet is requesting manual override
*/
unsigned char checkManualOverride() {
if(SCS1_SCRF) { //check flag
PWCODE = SCDR;
PW = PWCODE&keeppw;
if(PW == password) {
CODE = PWCODE&keepcode;
if(CODE == code0) {
return 1;
} //end if for code0 check
else if(CODE == code1) {
return 2;
} //end elseif for code1 check
else if(CODE == code2) {
return 3;
} //end else if for code1 check
else if(CODE == code3) {
return 4;
} //end else if for code3 check
else {
return 0;
}//do nothing if code is not valid
} //end if for password checking
else {
return 0;
} //do nothing if password is not correct
} //end if for serial input data register full check
while(repeat == '1') {
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
programDEV();
repeat = '0';
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
//LCDMenu();
repeat = '0';
} // end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
//progMenuTime();
repeat = '0';
} //end if LEFT
} //end while repeat
}
void progMenuTime() {
unsigned char repeat = '1';
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strprogmenu);
del1m(2);
strout(LCD_LINE2, (unsigned char *) strsetclk);
while(repeat == '1') {
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
programCLK();
repeat = '0';
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
//progMenuOutlets();
repeat = '0';
} // end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
//LCDMenu();
repeat = '0';
} //end if LEFT
} //end while repeat
}
void progMenuOutlets() {
unsigned char repeat = '1';
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strprogmenu);
del1m(2);
strout(LCD_LINE2, (unsigned char *) strprogdev);
Device 3: on: 0x0D
Device 4: off: 0x0E
Device 4: on: 0x0F
* Monday: 0x10 - 0x17
* Tuesday: 0x18 - 0x1F
* Wednesday: 0x20 - 0x27
* Thursday: 0x28 - 0x2F
* Friday: 0x30 - 0x37
* Saturday: 0x38 - 0x3F
* Get Device Data
* gets and saves updated on/off times for given day
* Reg 1: Off, Reg 2: On
* Bit 7 - 4: Hours (1-12
* Bits 3-1: Minute (0-5, x10)
* Bit 0: AM/PM
*/
void getDevData(unsigned char day) { //day was formerly today, until today was made global
unsigned char x;
unsigned char offset;// = (deviceNum - 1) * 2;
unsigned char i = TOTALDEVS;
//clearLCD();
// (1) read data from clock registers
switch(hexCode[day]) {
case '1': /********** SUNDAY **********/
//for(x = 8; x > 0; x--) {
//teststr[0] = hexCode[x];
//teststr[1] = ' ';
//teststr[2] = hexCode[SUNREG + x - 1];
//teststr[3] = ' ';
//teststr[4] = hexCode[(clkRegs[SUNREG+x-1] >> 4) & 0x0f];
//teststr[5] = hexCode[(clkRegs[SUNREG+x-1]) & 0x0f];
//teststr[6] = '\0';
//strout(LCD_LINE2, teststr);
//del1m(thousand);
// dayData[x-1] = clkRegs[SUNREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, SUNSTART);
break;
case '2': /********** MONDAY **********/
//for(x = 8; x > 0; x--) {
// dayData[x-1] = clkRegs[MONREG+x-1];
//}
}
/********************************************* FETCH DEVICE DATA STORED ON
RTC RAM *********************************************/
/*
* ---Time & Date--0x00 = clkRegs[0]: Seconds
0x01 = clkRegs[1]: Minutes
0x02 = clkRegs[2]: Hours
0x03 = clkRegs[3]:
0x04 = clkRegs[4]:
0x05 = clkRegs[5]:
0x06 = clkRegs[6]: Year
0x07 = clkRegs[7]: sqwout....
* ---Storage of On/Off times on RTC:--* Bits 7-4: Hour (1-12)
* Bits 3-1: Minute (0-5, x10)
* Bit 0: AM/PM
* x2 times per device x7 days x4 devices = 56 bytes (total RAM!)
*
* Sunday: 0x08 - 0x0F, offset: (deviceNumber - 1) * 2
Device 1: off: 0x08
Device 1: on: 0x09
Device 2: off: 0x0A
Device 2: on: 0x0B
Device 3: off: 0x0C
i2c_read2(CLOCK_RD_ADDR, dayData, 8, MONSTART);
break;
case '3': /********** TUESDAY **********/
//for(x = 8; x > 0; x--) {
//dayData[x-1] = clkRegs[TUEREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, TUESTART);
break;
case '4': /********** WEDNESDAY **********/
//for(x = 8; x > 0; x--) {
//dayData[x-1] = clkRegs[WEDREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, WEDSTART);
break;
case '5': /********** THURSDAY **********/
//for(x = 8; x > 0; x--) {
//dayData[x-1] = clkRegs[THUREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, THUSTART);
break;
case '6': /********** FRIDAY **********/
//for(x = 8; x > 0; x--) {
//dayData[x-1] = clkRegs[FRIREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, FRISTART);
break;
case '7': /********** SATURDAY **********/
//for(x = 8; x > 0; x--) {
//dayData[x-1] = clkRegs[SATREG+x-1];
//}
i2c_read2(CLOCK_RD_ADDR, dayData, 8, SATSTART);
break;
} //end switch
// (2) for each device....
for(; i > 0; i--) { //device 4 --> 3 --> 2 --> 1
offset = (i - 1) * 2; //index offset for dayData, based on device #
//e.g. dev 4 is stored at 6 and 7 (4 - 1 = 3 * 2 = 6)
//e.g. dev 3 is stored at 4 and 5 (3 - 1 = 2 * 2 = 4)
//e.g. dev 2 is stored at 2 and 3 (2 - 1 = 1 * 2 = 2)
//e.g. dev 1 is stored at 0 and 1 (1 - 1 = 0 * 2 = 0)
// (2a) process "off" time
if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'A') {
off10hr[i-1] = '1';
off09hr[i-1] = '0';
} else if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'B') {
off10hr[i-1] = '1';
off09hr[i-1] = '1';
} else if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'C') {
off10hr[i-1] = '1';
off09hr[i-1] = '2';
} else {
off10hr[i-1] = '0';
off09hr[i-1] = hexCode[(dayData[offset] >> 4) & 0x0f]; //up to 9
}
offpm[i-1] = hexCode[(dayData[offset] & 0x01)];
offmin[i-1] = hexCode[(dayData[offset] & 0x0e) >> 1]; //all but last bit (bits 3-1)
// (2b) process "on" time
if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'A') {
on10hr[i-1] = '1';
on09hr[i-1] = '0';
} else if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'B') {
on10hr[i-1] = '1';
on09hr[i-1] = '1';
} else if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'C') {
on10hr[i-1] = '1';
on09hr[i-1] = '2';
} else {
on10hr[i-1] = '0';
on09hr[i-1] = hexCode[(dayData[offset+1] >> 4) & 0x0f]; //up to 9
}
onpm[i-1] = hexCode[(dayData[offset+1] & 0x01)];
onmin[i-1] = hexCode[(dayData[offset+1] & 0x0e) >> 1]; //all but last bit (bits 3-1)
teststr[14] = 'M';
teststr[15] = '\0';
del1m(thousand); */
} //end for each device
timesToday = day;
}
/********************************************* PROGRAM DEVICE MAIN MENU
*********************************************/
void programDEV() {
unsigned char choice = 0; //0 = exit
unsigned char repeat = 1;
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
while(repeat) {
switch(choice) {
case 0:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) strexit);
break;
case 1:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 1");
break;
case 2:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 2");
break;
case 3:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 3");
/*teststr[0] = off10hr[i - 1];
teststr[1] = off09hr[i - 1];
teststr[2] = ':';
teststr[3] = offmin[i - 1];
teststr[4] = '0';
teststr[5] = offpm[i - 1];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[i - 1];
teststr[9] = on09hr[i - 1];
teststr[10] = ':';
teststr[11] = onmin[i - 1];
teststr[12] = '0';
teststr[13] = onpm[i - 1];
break;
case 4:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet 4");
break;
default:
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroutlet);
del1m(2);
strout(LCD_LINE2, (unsigned char *) "Outlet ?");
break;
} //end switch
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
//choice = (choice + 1) % 5;
if(choice == 4)
choice = 0;
else
choice++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
//choice = (choice - 1) % 5;
if(choice == 0)
choice = 4;
else
choice--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//repeat = '0';
if(choice != 0) {
repeat = '0';
programOutlet(choice);
break;
}
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
//repeat = 0;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
//repeat = 0;
} //end if LEFT
} //end repeat
}
/********************************************* PROGRAM OUTLET ON/OFF TIME
ON RTC *********************************************/
/* Program Outlet
* User will choose which device to program
* prior to calling this function.
* This function will go through the LCD menus
* to view/change on/off times for outletNum.
*/
void programOutlet(unsigned char outletNum) {
unsigned char repeat = '1', exit = '0';
unsigned char tempvar10, tempvar09, temppm, regOffset, addrOffset, temp;
unsigned char tempchars[8];
tempchars[7] = '\0';
/* CHANGE DAY OF THE WEEK */
while(exit == '0') {
clearLCD();
del1m(2);
strout(LCD_LINE1, (unsigned char *) strprogday);
today = 0; //start at exit --> user can choose a day of the week from there
repeat = '1';
while(repeat == '1') {
del1m(100);
switch(hexCode[today]) {
case '0': //done/exit
del1m(2);
strout(LCD_LINE2, (unsigned char *) strexit);
break;
case '1': //Sunday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strsun);
break;
case '2': //Monday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strmon);
break;
case '3': //Tuesday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strtue);
break;
case '4': //Wednesday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strwed);
break;
case '5': //Thursday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strthu);
break;
case '6': //Friday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strfri);
break;
case '7': //Saturday
del1m(2);
strout(LCD_LINE2, (unsigned char *) strsat);
break;
default: //unknown??
clearLCD();
del1m(2);
strout(LCD_LINE2, (unsigned char *) strohnoes);
} //end switch(dayofweek)
if(today == 0) { //exit back to choose outlet
exit = '1';
//programDEV();
}
else { //no exit
//del1m(thousand);
getDevData(today); //update all the variablesssssss
regOffset = (outletNum - 1) * 2;
//addrOffset = (regOffset >> 4) & 0x0f;
addrOffset = (regOffset) & 0x0f;
}
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
} //end while(repeat)
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(today == 7)
today = 0; //--> exit
else
today++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(today == 0)
today = 7;
else
today--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = '0';
temppm = 'A';
else if(offpm[outletNum - 1] == '1')
temppm = 'P';
else
temppm = '?';
while(repeat == '1') {
del1m(100);
tempchars[0] = tempvar10;
tempchars[1] = tempvar09;
tempchars[2] = temppm;
tempchars[3] = 'M';
tempchars[4] = '\0';
del1m(2);
strout(LCD_LINE2, tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12
if(tempvar09 == '2') { //12AM --> 01AM, 12PM --> 01PM
tempvar09 = '1';
tempvar10 = '0';
} //end if 12
else { //its 10 or 11
if(tempvar09 == '1') { //11PM --> 12AM, 11AM --> 12PM
if(temppm == 'A') temppm = 'P';
else if(temppm == 'P') temppm = 'A';
} //end if 11
tempvar09++;
} //end if 10 or 11
} //end hour MSB is 1
else if(tempvar10 == '0') { //its 01-09
if(tempvar09 == '9') { //9AM --> 10AM, 9PM --> 10PM
tempvar09 = '0';
tempvar10 = '1';
} //end if tempvar09 == 9
else { //tempvar09 between 1 and 8 --> just increment by 1
tempvar09++;
}
} //end hour MSB is 0
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12
if(tempvar09 == '0') { //10AM --> 09AM, 10PM --> 09PM
if(exit == '1') {
break;
}
/* CHANGE OFF HOUR */
clearLCD();
repeat = '1';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroffhour);
tempvar10 = off10hr[outletNum - 1];
tempvar09 = off09hr[outletNum - 1];
if(offpm[outletNum - 1] == '0')
tempvar09 = '9';
tempvar10 = '0';
} //end if 10
else { //its 11 or 12
if(tempvar09 == '2') { //12PM --> 11AM, 12AM --> 11PM
if(temppm == 'A') temppm = 'P';
else if(temppm == 'P') temppm = 'A';
}
tempvar09--;
} //end if 11 or 12
} //end hour MSB is 1
else if (tempvar10 == '0') { //its 01-09
if(tempvar09 == '1') { //01AM --> 12AM, 01PM --> 12PM
tempvar09 = '2'; //tempvar09++;
tempvar10 = '1';
}
else { //its between 02 and 09 --> just decrement by 1
tempvar09--;
}
} //end hour MSB is 0
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
// (1) update clkRegs for this device, day
// (2) update RTC regs with i2c_write2
off10hr[outletNum - 1] = tempvar10;
off09hr[outletNum - 1] = tempvar09;
if(temppm == 'A')
offpm[outletNum - 1] = '0';
else if(temppm == 'P')
offpm[outletNum - 1] = '1';
temp = ((((off10hr[outletNum - 1]*10) + off09hr[outletNum - 1]) & 0x0f) << 4) |
(((offmin[outletNum - 1] & 0x07) << 1) | (offpm[outletNum - 1] & 0x01)); //1001 0000 = 0x90
// /*
del1m(100);
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset], 1,
SUNSTART + addrOffset);
break;
case '2': //Monday
clkRegs[MONREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset],
1, MONSTART + addrOffset);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset], 1,
TUESTART + addrOffset);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset],
1, WEDSTART + addrOffset);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset],
1, THUSTART + addrOffset);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset], 1,
FRISTART + addrOffset);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset], 1,
SATSTART + addrOffset);
break;
} //end switch(today)
//*/
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
// (1) update clkRegs for this device, day
// (2) update RTC regs with i2c_write2
offmin[outletNum - 1] = tempvar10;
// /*
temp = ((((off10hr[outletNum - 1]*10) + off09hr[outletNum - 1]) & 0x0f) << 4) |
(((offmin[outletNum - 1] & 0x07) << 1) | (offpm[outletNum - 1] & 0x01)); //1001 0000 = 0x90
del1m(100);
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset], 1,
SUNSTART + addrOffset);
break;
case '2': //Monday
clkRegs[MONREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset],
1, MONSTART + addrOffset);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset], 1,
TUESTART + addrOffset);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset],
1, WEDSTART + addrOffset);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset],
1, THUSTART + addrOffset);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset], 1,
FRISTART + addrOffset);
} //end if LEFT
}//end while(repeat)
/* CHANGE OFF MINUTE */
//choose among: 00, 10, 20, 30, 40, 50
clearLCD();
repeat = '1';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
tempvar09 = '0';
del1m(2);
strout(LCD_LINE1, (unsigned char *) stroffmin);
tempvar10 = offmin[outletNum - 1];
while(repeat == '1') {
del1m(100);
tempchars[0] = off10hr[outletNum - 1];
tempchars[1] = off09hr[outletNum - 1];
tempchars[2] = ':';
tempchars[3] = tempvar10;
tempchars[4] = '0';
if(offpm[outletNum - 1] == '0')
tempchars[5] = 'A';
else if(offpm[outletNum - 1] == '1')
tempchars[5] = 'P';
else
tempchars[5] = '?';
tempchars[6] = 'M';
tempchars[7] = '\0';
del1m(2);
strout(LCD_LINE2, tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
//tempvar10 = (tempvar10 + 1)%6;
if(tempvar10 == '5') tempvar10 = '0';
else tempvar10++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
//tempvar10 = (tempvar10 - 1)%6;
if(tempvar10 == '0') tempvar10 = '5';
else tempvar10--;
break;
case '7': //Saturday
clkRegs[SATREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset], 1,
SATSTART + addrOffset);
break;
} //end switch(today)
//*/
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//end while(repeat)
/* CHANGE ON HOUR */
clearLCD();
repeat = '1';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
tempchars[4] = ' ';
tempchars[5] = ' ';
tempchars[6] = ' ';
del1m(2);
strout(LCD_LINE1, (unsigned char *) stronhour);
tempvar10 = on10hr[outletNum - 1];
tempvar09 = on09hr[outletNum - 1];
if(onpm[outletNum - 1] == '0')
temppm = 'A';
else if(onpm[outletNum - 1] == '1')
temppm = 'P';
else
temppm = '?';
while(repeat == '1') {
del1m(100);
tempchars[0] = tempvar10;
tempchars[1] = tempvar09;
tempchars[2] = temppm;
tempchars[3] = 'M';
tempchars[4] = '\0';
del1m(2);
strout(LCD_LINE2, tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12
if(tempvar09 == '2') { //12AM --> 01AM, 12PM --> 01PM
tempvar09 = '1';
tempvar10 = '0';
} //end if 12
else { //its 10 or 11
if(tempvar09 == '1') { //11PM --> 12AM, 11AM --> 12PM
if(temppm == 'A') temppm = 'P';
else if(temppm == 'P') temppm = 'A';
} //end if 11
tempvar09++;
} //end if 10 or 11
} //end hour MSB is 1
else if(tempvar10 == '0') { //its 01-09
if(tempvar09 == '9') { //9AM --> 10AM, 9PM --> 10PM
tempvar09 = '0';
tempvar10 = '1';
} //end if tempvar09 == 9
else { //tempvar09 between 1 and 8 --> just increment by 1
tempvar09++;
}
} //end hour MSB is 0
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12
if(tempvar09 == '0') { //10AM --> 09AM, 10PM --> 09PM
tempvar09 = '9';
tempvar10 = '0';
} //end if 10
else { //its 11 or 12
if(tempvar09 == '2') { //12PM --> 11AM, 12AM --> 11PM
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset +
1], 1, TUESTART + addrOffset + 0x01);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset +
1], 1, WEDSTART + addrOffset + 0x01);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset +
1], 1, THUSTART + addrOffset + 0x01);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset +
1], 1, FRISTART + addrOffset + 0x01);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset +
1], 1, SATSTART + addrOffset + 0x01);
break;
} //end switch(today)
//*/
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//end while(repeat)
/* CHANGE ON MINUTE */
if(temppm == 'A') temppm = 'P';
else if(temppm == 'P') temppm = 'A';
}
tempvar09--;
} //end if 11 or 12
} //end hour MSB is 1
else if (tempvar10 == '0') { //its 01-09
if(tempvar09 == '1') { //01AM --> 12AM, 01PM --> 12PM
tempvar09 = '2'; //tempvar09++;
tempvar10 = '1';
}
else { //its between 02 and 09 --> just decrement by 1
tempvar09--;
}
} //end hour MSB is 0
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
// (1) update clkRegs for this device, day
// (2) update RTC regs with i2c_write2
on10hr[outletNum - 1] = tempvar10;
on09hr[outletNum - 1] = tempvar09;
if(temppm == 'A')
onpm[outletNum - 1] = '0';
else if(temppm == 'P')
onpm[outletNum - 1] = '1';
// /*
temp = ((((on10hr[outletNum - 1]*10) + on09hr[outletNum - 1]) & 0x0f) << 4) |
(((onmin[outletNum - 1] & 0x07) << 1) | (onpm[outletNum - 1] & 0x01)); //0110 0110 = 0x66
del1m(100);
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset +
1], 1, SUNSTART + addrOffset + 0x01);
break;
case '2': //Monday
clkRegs[MONREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset +
1], 1, MONSTART + addrOffset + 0x01);
//choose among: 00, 10, 20, 30, 40, 50
clearLCD();
repeat = '1';
tempvar09 = '0';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
del1m(2);
strout(LCD_LINE1, (unsigned char *) stronmin);
tempvar10 = onmin[outletNum - 1];
while(repeat == '1') {
del1m(100);
tempchars[0] = on10hr[outletNum - 1];
tempchars[1] = on09hr[outletNum - 1];
tempchars[2] = ':';
tempchars[3] = tempvar10;
tempchars[4] = '0';
if(onpm[outletNum - 1] == '0')
tempchars[5] = 'A';
else if(onpm[outletNum - 1] == '1')
tempchars[5] = 'P';
else
tempchars[5] = '?';
tempchars[6] = 'M';
tempchars[7] = '\0';
del1m(2);
strout(LCD_LINE2, tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
//tempvar10 = (tempvar10 + 1)%6;
if(tempvar10 == '5') tempvar10 = '0';
else tempvar10++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
//tempvar10 = (tempvar10 - 1)%6;
if(tempvar10 == '0') tempvar10 = '5';
else tempvar10--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
// (1) update clkRegs for this device, day
// (2) update RTC regs with i2c_write2
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset +
1], 1, SATSTART + addrOffset + 0x01);
break;
} //end switch(today)
//*/
onmin[outletNum - 1] = tempvar10;
// /*
temp = ((((on10hr[outletNum - 1]*10) + on09hr[outletNum - 1]) & 0x0f) << 4) |
(((onmin[outletNum - 1] & 0x07) << 1) | (onpm[outletNum - 1] & 0x01)); //0110 0110 = 0x66
del1m(100);
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset +
1], 1, SUNSTART + addrOffset + 0x01);
break;
case '2': //Monday
clkRegs[MONREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset +
1], 1, MONSTART + addrOffset + 0x01);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset +
1], 1, TUESTART + addrOffset + 0x01);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset +
1], 1, WEDSTART + addrOffset + 0x01);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset +
1], 1, THUSTART + addrOffset + 0x01);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset +
1], 1, FRISTART + addrOffset + 0x01);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset + 1] = temp;
while(!SELECT) {} //so can look at
while(SELECT) {} //debounce
//TEST//
repeat = '1'; //go back into choosing day of the week
} //while !exit
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//end while(repeat)
//TEST//
del1m(1);
getDevData(today);
teststr[0] = off10hr[outletNum - 1];
teststr[1] = off09hr[outletNum - 1];
teststr[2] = ':';
teststr[3] = offmin[outletNum - 1];
teststr[4] = '0';
teststr[5] = offpm[outletNum - 1];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[outletNum - 1];
teststr[9] = on09hr[outletNum - 1];
teststr[10] = ':';
teststr[11] = onmin[outletNum - 1];
teststr[12] = '0';
teststr[13] = onpm[outletNum - 1];
teststr[14] = 'M';
teststr[15] = '\0';
del1m(2);
strout(LCD_LINE1, "is this what you saved?");
del1m(2);
strout(LCD_LINE2, teststr);
case '6': //Friday
strout(LCD_LINE2, (unsigned char *) strfri);
break;
case '7': //Saturday
strout(LCD_LINE2, (unsigned char *) strsat);
break;
default: //unknown??
strout(LCD_LINE2, (unsigned char *) strohnoes);
} //end switch(dayofweek)
}
/********************************************* PROGRAM THE DATE AND TIME
ON RTC *********************************************/
/* Program Clock
* This function will go through the LCD menus
* to view/change the set time and date.
*/
void programCLK() {
unsigned char repeat = '1';
unsigned char tempvar, tempvar10, tempvar09, temppm;
unsigned char tempchars[5] = " ";
tempchars[4] = '\0';
getTime(); //get initial values
/* CHANGE DAY OF THE WEEK */
clearLCD();
strout(LCD_LINE1, (unsigned char *) strweekday);
tempvar = hexCode[dayofweek];
while(repeat == '1') {
switch(tempvar) {
case '1': //Sunday
strout(LCD_LINE2, (unsigned char *) strsun);
break;
case '2': //Monday
strout(LCD_LINE2, (unsigned char *) strmon);
break;
case '3': //Tuesday
strout(LCD_LINE2, (unsigned char *) strtue);
break;
case '4': //Wednesday
strout(LCD_LINE2, (unsigned char *) strwed);
break;
case '5': //Thursday
strout(LCD_LINE2, (unsigned char *) strthu);
break;
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar == '7') //saturday
tempvar = '1'; //--> sunday
else
tempvar++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar == '1') //sunday
tempvar = '7'; //--> saturday
else
tempvar--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
clkRegs[3] = ((tempvar) & 0x0f);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[3], 1, 3);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
} //while(repeat)
/* CHANGE MONTH */
clearLCD();
repeat = '1';
strout(LCD_LINE1, (unsigned char *) strmonth);
tempvar10 = hexCode[months10];
tempvar09 = hexCode[months09];
while(repeat == '1') {
if(tempvar10 == '1') {
switch(tempvar09) {
case '0': //10 October
strout(LCD_LINE2, (unsigned char *) stroct);
break;
case '1': //11 November
strout(LCD_LINE2, (unsigned char *) strnov);
break;
case '2': //12 December
strout(LCD_LINE2, (unsigned char *) strdec);
break;
} //end switch(months09)
} //end if months10 == 1
else { //months10 == 0
switch(tempvar09) {
case '1': //1 January
strout(LCD_LINE2, (unsigned char *) strjan);
break;
case '2': //2 February
strout(LCD_LINE2, (unsigned char *) strfeb);
break;
case '3': //3 March
strout(LCD_LINE2, (unsigned char *) strmar);
break;
case '4': //4 April
strout(LCD_LINE2, (unsigned char *) strapr);
break;
case '5': //5 May
strout(LCD_LINE2, (unsigned char *) strmay);
break;
case '6': //6 June
strout(LCD_LINE2, (unsigned char *) strjun);
break;
case '7': //7 July
strout(LCD_LINE2, (unsigned char *) strjul);
break;
case '8': //8 August
strout(LCD_LINE2, (unsigned char *) straug);
//update the clock register
clkRegs[5] = (((0x0f & tempvar10) << 4) | (0x0f & tempvar09));
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[5], 1, 5);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//while(repeat)
/* CHANGE DAY OF THE MONTH */
clearLCD();
repeat = '1';
strout(LCD_LINE1, (unsigned char *) strdate);
tempvar10 = hexCode[date10];
tempvar09 = hexCode[date09];
while(repeat == '1') {
tempchars[0] = tempvar10;
tempchars[1] = tempvar09;
strout(LCD_LINE2, (unsigned char *) tempchars);
//while(!UP && !DOWN && !SELECT);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar10 == '3') { //31 days: jan (01), march (03), may (05), july (07), oct (10), dec (12);
30 days: april (04), june (06), aug (08), sept (09), nov (11)
if(hexCode[months10] == '0') {
if(hexCode[months09] == '2' || hexCode[months09] == '4' || hexCode[months09] == '6') {
//if february, april, june
tempvar10 = '0';
tempvar09 = '1';
}
else if(hexCode[months09] == '1' || hexCode[months09] == '3' || hexCode[months09] ==
'5' || hexCode[months09] == '7') { //january, march, may, july
if(tempvar09 == '1') {
tempvar10 = '0';
break;
case '9': //9 September
strout(LCD_LINE2, (unsigned char *) strsep);
break;
default: //unknown??
strout(LCD_LINE2, (unsigned char *) strohnoes);
} //end switch(months09)
} //end else months10 == 0
//while(!UP && !DOWN && !SELECT);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar10 == '1') {
if(tempvar09 == '0' || tempvar09 == '1') tempvar09++;
else { //12 December --> 01 January
tempvar10 = '0';
tempvar09 = '1';
} //months09 != 0
} //months10 ==1
else { //months10 == 0
if(tempvar09 <= '8') tempvar09++;
else { //09 September --> 10 October
tempvar10 = '1';
tempvar09 = '0';
} //months09 > 8
} //months10 == 1
} //if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar10 == '1') {
if(tempvar09 == '2' || tempvar09 == '1') tempvar09--;
else { //10 October --> 09 September
tempvar10 = '0';
tempvar09 = '9';
}
} //months10 ==1
else {
if(tempvar09 > '1') tempvar09--;
else { //01 January --> 12 December
tempvar10 = '1';
tempvar09 = '2';
} //else months09 == 1
} //else months10 == 0
} //if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
tempvar09 = '1';
}
else if(tempvar09 == '0') {
tempvar09 = '1';
}
} //end if january, march, may, july
} //end if months10 == 0 (january - september except february)
else if(hexCode[months10] == '1') {
if(hexCode[months09] == '1') { //november
tempvar10 = '0';
tempvar09 = '1';
}
else if(hexCode[months09] == '0' || hexCode[months09] == '2') { //october or december
if(tempvar09 == '1') {
tempvar10 = '0';
tempvar09 = '1';
}
else if(tempvar09 == '0') { tempvar09 = '1'; }
} //end if months10 == 1 (october or november or december)
} //end if months10 == 1
} //end if date10 == 3
else if(tempvar10 == '2') {
if(tempvar09 == '9') {
if(hexCode[months10] == '0' && hexCode[months09] == '2') { //february
tempvar10 = '0';
tempvar09 = '1';
}
else { //not february
tempvar10 = '3';
tempvar09 = '0';
}
} //end if date09 == 9
else { //date09 < 9
tempvar09++;
} //end if date09 < 9
} //end if date10 == 2
else if(tempvar10 == '1' || tempvar10 == '0') { //date10 = 1 or 0
if(tempvar09 == '9') {
tempvar10++;
tempvar09 = '0';
} //end if date09 == 9
else {
tempvar09++;
}
} //end if date10 == 1 || 0
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar10 == '0' && tempvar09 == '1') {
if(hexCode[months10] == '0') { //months: january-september
if(hexCode[months09] == '2') { //february --> max 29 days
tempvar10 = '2';
tempvar09 = '9';
} //end if february
else if(hexCode[months09] == '1' || hexCode[months09] == '3' || hexCode[months09] ==
'5' || hexCode[months09] == '7' || hexCode[months09] == '8') { //months with 31 days (jan, mar,
may, july, aug)
tempvar10 == '3';
tempvar09 == '1';
} //end if month with 31 days
else if(hexCode[months09] == '4' || hexCode[months09] == '6' || hexCode[months09] ==
'9') { //months with 30 days (april, june, sept)
tempvar10 == '3';
tempvar09 == '0';
} //end if month with 30 days
} //end if months10 = 0
else if(hexCode[months10] == '1') {
if(hexCode[months09] == '1') { //november has 30 days
tempvar10 = '3';
tempvar09 = '0';
}
else if(hexCode[months09] == '0' || hexCode[months09] == '2') { //october and december
have 31 days
tempvar10 = '3';
tempvar09 = '1';
}
} //end if months10 = 1
} //end if date == 01
else if(date09 == 0) { //date != 01, date09 == 0
tempvar10--;
tempvar09--;
}
else { //date != 01, date09 > 0
tempvar09--;
}
} //if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
if(tempvar09 == '0') {
tempvar09 = '9';
if(tempvar10 == '0') tempvar10 = '9';
else tempvar10--;
} //end years09 == 0
else tempvar09--;
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
clkRegs[6] = (((0x0f & tempvar10) << 4) | (0x0f & tempvar09));
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[6], 1, 6);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
} //end while(repeat)
/* CHANGE HOUR */
clearLCD();
repeat = '1';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
strout(LCD_LINE1, (unsigned char *) strtimehr);
tempvar10 = hexCode[hours10];
tempvar09 = hexCode[hours09];
tempchars[0] = tempvar10; //NEW//
tempchars[1] = tempvar09;
if(hexCode[pm] == '1') temppm = 'P'; //NEW//
else temppm = 'A'; //NEW//
tempchars[2] = temppm;
//update the clock register
clkRegs[4] = (((0x0f & tempvar10) << 4) | (0x0f & tempvar09));
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[4], 1, 4);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//while(repeat)
/* CHANGE YEAR */
clearLCD();
repeat = '1';
strout(LCD_LINE1, (unsigned char *) stryear);
tempchars[0] = '2';
tempchars[1] = '0';
tempvar10 = hexCode[years10];
tempvar09 = hexCode[years09];
while(repeat == '1') {
tempchars[2] = tempvar10;
tempchars[3] = tempvar09;
strout(LCD_LINE2, (unsigned char *) tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar09 == '9') {
tempvar09 = '0';
if(tempvar10 == '9') tempvar10 = '0';
else tempvar10++;
} //end years09 == 9
else tempvar09++;
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
tempchars[3] = 'M';
while(repeat == '1') {
tempchars[0] = tempvar10; //NEW//
tempchars[1] = tempvar09;
tempchars[2] = temppm; //NEW//
tempchars[3] = 'M';
strout(LCD_LINE2, (unsigned char *) tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12 //NEW//
if(tempvar09 == '2') { //12AM --> 01AM, 12PM --> 01PM
tempvar09 = '1';
tempvar10 = '0';
} //end if 12
else { //its 10 or 11
if(tempvar09 == '1') { //11PM --> 12AM, 11AM --> 12PM
//OLD//if(tempvar10 == '1') tempvar10 = '3';
//OLD//else if(tempvar10 == '3') tempvar10 = '1';
if(temppm == 'A') temppm = 'P'; //NEW//
else if(temppm == 'P') temppm = 'A'; //NEW//
}
tempvar09++;
} //end if 10 or 11
} //end hour MSB is 1
else if(tempvar10 == '0') { //its 01-09 //NEW//
if(tempvar09 == '9') {
tempvar09 = '0';
tempvar10 = '1'; //9AM --> 10AM, 9PM --> 10PM
} //end if tempvar09 == 9
else { //tempvar09 between 1 and 8 --> just increment by 1
tempvar09++;
}
} //end hour MSB is 0
} //end if UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar10 == '1') { //its 10, 11, or 12
if(tempvar09 == '0') { //10AM --> 09AM, 10PM --> 09PM
tempvar09 = '9';
tempvar10 = '0';
} //end if 10
else { //its 11 or 12
if(tempvar09 == '2') { //12PM --> 11AM, 12AM --> 11PM
//OLD//if(tempvar10 == '3') tempvar10 = '1';
//OLD//else if(tempvar10 == '1') tempvar10 = '3';
if(temppm == 'A') temppm = 'P'; //NEW//
else if(temppm == 'P') temppm = 'A'; //NEW//
}
tempvar09--;
} //end if 11 or 12
} //end hour MSB is 1s
else if(tempvar10 == '0') { //its 01-09 //NEW//
if(tempvar09 == '1') { //01AM --> 12AM, 01PM --> 12PM
tempvar09 = '2'; //tempvar09++;
tempvar10 = '1';
}
else { //its between 02 and 09 --> just decrement by 1
tempvar09--;
}
} //end hour MSB is 0
} //end if DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
if(temppm == 'A')
pm = 0;
else
pm = 1;
clkRegs[2] = (((0x01 & pm) << 5) | ((0x01 & tempvar10) << 4) | (0x0f & tempvar09));
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[2], 1, 2);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
}//end while(repeat)
} //end DOWN
else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
//update the clock register
clkRegs[1] = (((0x0f & tempvar10) << 4) | (0x0f & tempvar09));
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[1], 1, 1);
repeat = '0';
break;
} //end if SELECT
else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
repeat = '0';
break;
} //end if LEFT
} //end while(repeat)
strout(LCD_LINE1, "Select to Return Home");
while(!SELECT) {
testCLK();
del1m(1000);
}
while(SELECT){} //debounce
}
/* This program tests the DS1307 Real Time Clock with I2C interface
* An LED on pin 2 of the MC908JL16 will blink every other second
* An LED connected to the SQW output of the Clock will blink at 1Hz
* The LCD will display the time
*/
void testCLK() {
//unsigned char time[24]; //Day, MO/DD/YR HH:MM xm
time[23] = '\0';
del1m(1);
i2c_read2(CLOCK_RD_ADDR, clkRegs, 8, 0); //read all 8 main registers
/* CHANGE MINUTE */
clearLCD();
repeat = '1';
tempchars[0] = ' ';
tempchars[1] = ' ';
tempchars[2] = ' ';
tempchars[3] = ' ';
strout(LCD_LINE1, (unsigned char *) strtimemin);
tempvar10 = hexCode[minutes10];
tempvar09 = hexCode[minutes09];
while(repeat == '1') {
tempchars[0] = tempvar10;
tempchars[1] = tempvar09;
strout(LCD_LINE2, (unsigned char *) tempchars);
if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
if(tempvar09 == '9') {
if(tempvar10 == '5') {
tempvar10 = '0';
tempvar09 = '0';
}
else { //minutes10 < 5 && minutes09 == 9
tempvar10++;
tempvar09 = '0';
}
}
else { //minutes09 < 9
tempvar09++;
}
} //end UP
else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
if(tempvar09 == '0') {
if(tempvar10 == '0') {
tempvar10 = '5';
tempvar09 = '9';
}
else { //minutes10 > 0 && minutes09 == 0
tempvar10--;
tempvar09 = '9';
}
}
else { //minutes09 > 0
tempvar09--;
}
// day of the week
dayofweek = (clkRegs[3] & 0x07); //only care about 3 lowest bits
switch(hexCode[dayofweek]) {
case '1': //Sunday
time[0] = 'S';
time[1] = 'u';
time[2] = 'n';
break;
case '2': //Monday
time[0] = 'M';
time[1] = 'o';
time[2] = 'n';
break;
case '3': //Tuesday
time[0] = 'T';
time[1] = 'u';
time[2] = 'e';
break;
case '4': //Wednesday
time[0] = 'W';
time[1] = 'e';
time[2] = 'd';
break;
case '5': //Thursday
time[0] = 'T';
time[1] = 'h';
time[2] = 'u';
break;
case '6': //Friday
time[0] = 'F';
time[1] = 'r';
time[2] = 'i';
break;
case '7': //Saturday
time[0] = 'S';
time[1] = 'a';
time[2] = 't';
break;
default: //unknown??
time[0] = '?';
time[1] = '?';
time[2] = '?';
}
time[3] = ',';
time[4] = ' ';
seconds10 = ((clkRegs[0] >> 4) & 0x07); //only 3 10's bits
seconds09 = (clkRegs[0] & 0x0f);
time[20] = hexCode[seconds10];
time[21] = hexCode[seconds09];
if(hexCode[pm] == '0')
time[22] = 'A';
else if(hexCode[pm] == '1')
time[22] = 'P';
else
time[22] = '?';
time[23] = 'M';
//month
months10 = (clkRegs[5] >> 4) & 0x01; //only 1 10's bit
months09 = (clkRegs[5] & 0x0f);
time[5] = hexCode[months10];
time[6] = hexCode[months09];
time[7] = '/';
//day of the month
date10 = (clkRegs[4] >> 4) & 0x03; //only 2 10's bits
date09 = (clkRegs[4] & 0x0f);
time[8] = hexCode[date10];
time[9] = hexCode[date09];
time[10] = '/';
//year
years10 = (clkRegs[6] >> 4) & 0x0f;
years09 = (clkRegs[6] & 0x0f);
time[11] = hexCode[years10];
time[12] = hexCode[years09];
time[13] = ' ';
//hour
/*if((hexCode[(clkRegs[2] >> 4) & 0x0f] == '0') || (hexCode[(clkRegs[2] >> 4) & 0x0f] == '1'))
{
pm = 'A';
}
else if((hexCode[(clkRegs[2] >> 4) & 0x0f] == '2') || (hexCode[(clkRegs[2] >> 4) & 0x0f] ==
'3')) {
pm = 'P';
} */
pm = ((clkRegs[2] >> 5) & 0x01);
hours10 = (clkRegs[2] >> 4) & 0x01; //1st bit only - //NEW//
hours09 = (clkRegs[2] & 0x0f);
time[14] = hexCode[hours10]; //NEW//
time[15] = hexCode[hours09];
time[16] = ':';
//minute
minutes10 = (clkRegs[1] >> 4) & 0x07; //only 3 10's bits
minutes09 = (clkRegs[1] & 0x0f);
time[17] = hexCode[minutes10];
time[18] = hexCode[minutes09];
time[19] = ':';
/* turn on LED in port A bit 0 for n msec, then turn off */
void blink(int n) {
PTA_PTA0 = 0; //turn on LED
del1m(n); //leave on n msec
PTA_PTA0 = 1; //turn off LED
}
/*
void testOutlets() {
del1m(2);
while(one) {
OUTLET1 = 1;
strout(LCD_LINE1, "outlet 1");
del1m(thousand);
OUTLET1 = 0;
OUTLET2 = 1;
strout(LCD_LINE1, "outlet 2");
del1m(thousand);
OUTLET2 = 0;
OUTLET3 = 1;
strout(LCD_LINE1, "outlet 3");
del1m(thousand);
OUTLET3 = 0;
del1m(2);
strout(LCD_LINE2, (unsigned char *) time);
}
/* Get Time
* Retrieves Time & Date Register Values
* Saves to Global Variables
*/
void getTime() {
i2c_read2(CLOCK_RD_ADDR, clkRegs, 7, 0);
seconds10 = ((clkRegs[0] >> 4) & 0x07); //only 3 10's bits
seconds09 = (clkRegs[0] & 0x0f);
minutes10 = (clkRegs[1] >> 4) & 0x07; //only 3 10's bits
minutes09 = (clkRegs[1] & 0x0f);
pm = ((clkRegs[2] >> 5) & 0x01);
hours10 = (clkRegs[2] >>4) & 0x01; //1st bit only - //NEW//
hours09 = (clkRegs[2] & 0x0f);
dayofweek = (clkRegs[3] & 0x07); //only care about 3 lowest bits
date10 = (clkRegs[4] >> 4) & 0x03; //only 2 10's bits
date09 = (clkRegs[4] & 0x0f);
months10 = (clkRegs[5] >> 4) & 0x01; //only 1 10's bit
months09 = (clkRegs[5] & 0x0f);
years10 = (clkRegs[6] >> 4) & 0x0f;
years09 = (clkRegs[6] & 0x0f);
}
/* ----------------------------------------------------------------------- */
/**************************************** Test Functions
****************************************/
* Print Blanks on line 2
* Bring cursor home
*/
void clearLCD() {
del1m(2);
strout(LCD_LINE1, (unsigned char *) clearstr); // clear line 1
del1m(2);
strout(LCD_LINE2, (unsigned char *) clearstr); //clear line 2
cmdout(0x02); //cursor home
}
/* charout - Print the character 'c' at LCD RAM location "x". */
void charout(int x, unsigned char c) {
unsigned char ch;
cmdout(x | 0x80); // Make A contain a Set Display Address command
while ((ch = c) != (unsigned char) NULL) {
datout(c); // Output the next character
}
}
/* strout - Print the contents of the character string "s" starting at LCD
RAM location "x". The string must be terminated by a zero byte. */
void strout(int x, unsigned char *s) {
unsigned char ch;
cmdout(x | 0x80); // Make A contain a Set Display Address command
OUTLET4 = 1;
strout(LCD_LINE1, "outlet 4");
del1m(thousand);
OUTLET4 = 0;
}
}*/
/**************************************** Test Functions
****************************************/
/**************************************** LCD
****************************************/
/* Clear Contents of LCD:
* Bring cursor home
* Print blanks on line 1
while ((ch = *s++) != (unsigned char) NULL) {
datout(ch); // Output the next character
}
}
/* datout - Output a byte to the LCD display data register (the display)
and wait for the busy flag to reset. */
void datout(unsigned char x) {
PTD = 0x02;
// Set R/W=0, E=0, RS=1
nibout(x);
// Put data bits 4-7 in PTB
nibout(x << 4); // Put data bits 0-3 in PTB
busywt();
// Wait for BUSY flag to reset
}
/* cmdout - Output a byte to the LCD display instruction register and
wait for the busy flag to reset. */
void cmdout(unsigned char x) {
PTD = 0;
// Set R/W=0, E=0, RS=0
nibout(x);
// Output command bits 4-7
nibout(x << 4); // Output command bits 0-3
busywt();
// Wait for BUSY flag to reset
}
/* nibout - Puts bits 4-7 from x into the four bits of Port B that we're
using to talk to the LCD. The other bits of Port B are unchanged.
Toggle the E control line low-high-low. */
void nibout(unsigned char x) {
#ifdef NIBBLE_HIGH
PTB = (x & 0xf0) | (PTB & 0x0f); // Use bits 4-7
//PTB_PTB4 = x & 0x10;
//PTB_PTB5 = x & 0x20;
//PTB_PTB6 = x & 0x30;
//PTB_PTB7 = x & 0x80;
#else
PTB = ((x >> 4) & 0x0f) | (PTB & 0xf0); // Use bits 0-3
//PTB_PTB0 = x & 0x01;
//PTB_PTB1 = x & 0x02;
//PTB_PTB2 = x & 0x04;
//PTB_PTB3 = x & 0x08;
#endif
PTD_PTD3 = 1;
// Set E to 1
PTD_PTD3 = 0;
// Set E to 0
}
/* initialize - Do various things to force a initialization of the LCD
display by instructions, and then set up the display parameters and
turn the display on. */
void initializeLCD() {
del1m(15);
// Delay at least 15ms
iniout(0x30);
del1m(4);
// Send a 0x30
// Delay at least 4msec
iniout(0x30);
del40u(3);
// Send a 0x30
// Delay at least 100usec
iniout(0x30);
// Send a 0x30
#else
//DDRB = 0x0f;
// Set PTB for output
DDRB_DDRB0 = 1;
DDRB_DDRB1 = 1;
DDRB_DDRB2 = 1;
DDRB_DDRB3 = 1;
#endif
}
iniout(0x20);
busywt();
// Function Set: 4-bit interface
// Wait for BUSY flag to reset
cmdout(0x28);
// Function Set: 4-bit interface, 2 lines
cmdout(0x0f);
// Display and cursor on
}
/* iniout - Output a byte to the LCD control register. Same as the "cmdout"
function but it doesn't wait for the BUSY flag since that flag isn't
working during initialization. */
void iniout(unsigned char x) {
PTD = 0;
// Set R/W=0, E=0, RS=0
nibout(x);
}
/* busywt - Wait for the BUSY flag to reset */
void busywt() {
unsigned char bf;
//DDRB = 0;
// Set PTB for input
DDRB_DDRB4 = 0;
DDRB_DDRB5 = 0;
DDRB_DDRB6 = 0;
DDRB_DDRB7 = 0;
PTD = 0x04;
// Set E=0, R/W=1, RS=0
do {
PTD_PTD3 = 1; // Set E=1
#ifdef NIBBLE_HIGH
bf = PTB & 0x80; // Read status register bits 4-7
#else
bf = PTB & 0x08; // Read status register bits 4-7
#endif
PTD_PTD3 = 0; // Set E=0
PTD_PTD3 = 1; // Set E=1, ignore bits 0-3
PTD_PTD3 = 0; // Set E=0
} while (bf != 0); // If Busy (PTB7=1), loop
#ifdef NIBBLE_HIGH
//DDRB = 0xf0;
// Set PTB for output
DDRB_DDRB4 = 1;
DDRB_DDRB5 = 1;
DDRB_DDRB6 = 1;
DDRB_DDRB7 = 1;
clkRegs[10] = clkRegs[11] = clkRegs[12] = clkRegs[13] = clkRegs[14] = clkRegs[15] =
clkRegs[16] = clkRegs[17] = clkRegs[18] = clkRegs[19] = 0xC0;
clkRegs[20] = clkRegs[21] = clkRegs[22] = clkRegs[23] = clkRegs[24] = clkRegs[25] =
clkRegs[26] = clkRegs[27] = clkRegs[28] = clkRegs[29] = 0xC0;
clkRegs[30] = clkRegs[31] = clkRegs[32] = clkRegs[33] = clkRegs[34] = clkRegs[35] =
clkRegs[36] = clkRegs[37] = clkRegs[38] = clkRegs[39] = 0xC0;
clkRegs[40] = clkRegs[41] = clkRegs[42] = clkRegs[43] = clkRegs[44] = clkRegs[45] =
clkRegs[46] = clkRegs[47] = clkRegs[48] = clkRegs[49] = 0xC0;
clkRegs[50] = clkRegs[51] = clkRegs[52] = clkRegs[53] = clkRegs[54] = clkRegs[55] = 0xC0;
/**************************************** LCD
****************************************/
i2c_write2(CLOCK_WR_ADDR, clkRegs, 64, 0);
}
/**************************************** I2C - Real Time Clock
****************************************/
/* i2c_init - Initialize the MMIIC port */
void i2c_init(unsigned char bdiv) {
MIMCR_MMBR = bdiv;
// Set baud rate divisor
MMCR_MMEN = 1;
// Enable MMIIC
}
/* clk_init - Initialize the Clock
* The Clock is initialized to 12:00:00 PM Wednesday 04/01/09
* The SQWE pin outputs a 1Hz square wave
*
* Initialize the RTC RAM for on/off times
* Initialize the on/off times in RTC RAM
* Bits 7-4: Hour (1-12)
* Bits 3-1: Minute (0-5, x10)
* Bit 0: AM/PM
* INIT: 12AM: 1100 000 0 = 0xC0
*/
void clk_init() {
clkRegs[0] = 0x00; //Seconds: 00
clkRegs[1] = 0x00; //Minutes: 00
clkRegs[2] = 0x72; //Hour: 12pm
clkRegs[3] = 0x04; //Day of the week: Wednesday
clkRegs[4] = 0x01; //Date: 01
clkRegs[5] = 0x04; //Month: 04
clkRegs[6] = 0x09; //Year: 2009
clkRegs[7] = 0x10; //outputs 1hz square wave from SQWE pin
//the rest: RAM (on/off times)
clkRegs[8] = clkRegs[9] = 0xC0;
void clkRegs_init() {
clkRegs[8] = clkRegs[9] = 0xC0;
clkRegs[10] = clkRegs[11] = clkRegs[12] = clkRegs[13] = clkRegs[14] = clkRegs[15] =
clkRegs[16] = clkRegs[17] = clkRegs[18] = clkRegs[19] = 0xC0;
clkRegs[20] = clkRegs[21] = clkRegs[22] = clkRegs[23] = clkRegs[24] = clkRegs[25] =
clkRegs[26] = clkRegs[27] = clkRegs[28] = clkRegs[29] = 0xC0;
clkRegs[30] = clkRegs[31] = clkRegs[32] = clkRegs[33] = clkRegs[34] = clkRegs[35] =
clkRegs[36] = clkRegs[37] = clkRegs[38] = clkRegs[39] = 0xC0;
clkRegs[40] = clkRegs[41] = clkRegs[42] = clkRegs[43] = clkRegs[44] = clkRegs[45] =
clkRegs[46] = clkRegs[47] = clkRegs[48] = clkRegs[49] = 0xC0;
clkRegs[50] = clkRegs[51] = clkRegs[52] = clkRegs[53] = clkRegs[54] = clkRegs[55] = 0xC0;
}
void clkRAM_init() {
unsigned char clkRAM[56];
clkRAM[0] = clkRAM[1] = clkRAM[2] = clkRAM[3] = clkRAM[4] = clkRAM[5] =
clkRAM[6] = clkRAM[7] = clkRAM[8] = clkRAM[9] = 0xC0;
clkRAM[10] = clkRAM[11] = clkRAM[12] = clkRAM[13] = clkRAM[14] = clkRAM[15] =
clkRAM[16] = clkRAM[17] = clkRAM[18] = clkRAM[19] = 0xC0;
clkRAM[20] = clkRAM[21] = clkRAM[22] = clkRAM[23] = clkRAM[24] = clkRAM[25] =
clkRAM[26] = clkRAM[27] = clkRAM[28] = clkRAM[29] = 0xC0;
clkRAM[30] = clkRAM[31] = clkRAM[32] = clkRAM[33] = clkRAM[34] = clkRAM[35] =
clkRAM[36] = clkRAM[37] = clkRAM[38] = clkRAM[39] = 0xC0;
clkRAM[40] = clkRAM[41] = clkRAM[42] = clkRAM[43] = clkRAM[44] = clkRAM[45] =
clkRAM[46] = clkRAM[47] = clkRAM[48] = clkRAM[49] = 0xC0;
clkRAM[50] = clkRAM[51] = clkRAM[52] = clkRAM[53] = clkRAM[54] = clkRAM[55] =
0xC0;
del1m(1);
i2c_write2(CLOCK_WR_ADDR, clkRAM, 56, 0x08);
}
MMCR_MMTXAK = 0;
// MCU will ACK received data
MMADR = CLOCK_WR_ADDR;
// Device address -> address reg.
//MMDTR = ADDR.Bytes.Address_H; // High byte of data address
MMDTR = reg; //data address
MIMCR_MMRW = 0;
// Set for transmit
MIMCR_MMAST = 1;
// Initiate transfer
/* i2c_write2 - write bytes to an I2C device (two byte address) */
void i2c_write2(unsigned char device_addr, unsigned char *p, int n, byte reg) {
//ADDR.Address = reg;
// Copy address to struct
while (MIMCR_MMBB);
// Wait for bus not busy
while (!(MMSR_MMTXBE));
// Wait for TX buffer
empty////////////////////////////////STUCK HERE: MMSR_MMTXBE never goes to 1
MMADR = device_addr;
// Device address -> address reg
//MMDTR = ADDR.Bytes.Address_H; // High byte of data address
MMDTR = reg;
MIMCR_MMRW = 0;
// Set for transmit
MIMCR_MMAST = 1;
// Start transmission
//while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
//MMDTR = ADDR.Bytes.Address_L; // Low byte of data address
//while (MMSR_MMRXAK);
// Wait for ACK from slave
//while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
//MMDTR = ADDR.Bytes.Address_L; // Low byte of data address
//while (MMSR_MMRXAK);
// Wait for ACK from slave
while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
MMDTR = 0xff;
// Dummy data to get ACK clock
while (MMSR_MMRXAK);
// Wait for ACK from slave
MMADR = device_addr;
// device address -> address reg.
//MMDTR = 0xff;
// dummy data -> data reg.
MIMCR_MMRW = 1;
// Set for receive
MMCR_REPSEN = 1;
// Enable repeated start
MIMCR_MMAST = 1;
// Initiate transfer
while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
MMDTR = 0xff;
// Dummy data -> data reg
while (MMSR_MMRXAK);
// Wait for ACK from slave
while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
MMDTR = *p++;
// First byte of data to write
while (MMSR_MMRXAK);
// Wait for ACK from slave
while (n > 0) {
n--;
// Decrement count
while (!(MMSR_MMTXBE));
// Wait for TX buffer empty
if (n == 0)
// Is this the last byte?
MMDTR = 0xff;
// Yes. dummy data -> DTR
else
MMDTR = *p++;
// No. next data -> DTR
while (MMSR_MMRXAK);
// Wait for ACK from slave
}
MIMCR_MMAST = 0;
// Generate STOP bit
//MMCR_MMEN = 0;
//MMCR_MMEN = 1;
n--;
// Loop n-1 times before last read
while (n > 0) {
// Up to last byte
while (!(MMSR_MMRXBF));
// Wait for RX buffer full
*p++ = MMDRR;
// Get data
n--;
// Decrement total count
}
MMCR_MMTXAK = 1;
// Don't send ACK for last byte
while (!(MMSR_MMRXBF));
// Wait for RX buffer full
*p++ = MMDRR;
// Get data
MIMCR_MMAST = 0;
// Generate STOP bit
// disable MMIIC
// Enable MMIIC
}
MMCR_MMEN = 0;
MMCR_MMEN = 1;
/* i2c_read2 - read bytes from an I2C device (two byte address) */
void i2c_read2(unsigned char device_addr, unsigned char *p, int n, byte reg) {
unsigned char x;
x = MMDRR;
//ADDR.Address = reg;
// disable MMIIC
// Enable MMIIC
}
/**************************************** I2C - Real Time Clock
****************************************/
// This should clear the MMRXBF flag
// Copy address to struct
/* sci_init - Initialize the SCI port */
void sci_init(void) {
SCC1_ENSCI = 1;
// Enable SCI
/* Set output for 9600 baud. Assumes a 9.8304MHz clock */
SCBR_SCP = 0;
// Baud rate prescaler = 1
SCBR_SCR = 2;
// Baud rate divisor = 4
SCC2_TE = 1;
// Enable transmitter
}
/* sciout - Output a byte to SCI port */
void sciout(unsigned char ch) {
while (SCS1_SCTE == 0);
SCDR = ch;
}
/* sciouts - Print the contents of the character string "s" out the SCI
port. The string must be terminated by a zero byte */
void sciouts(unsigned char *s) {
unsigned char ch;
while ((ch = *s++) != (unsigned char) NULL)
sciout(ch);
/**************************************** SCI Port
****************************************/
u1:
mov #13,delay0 ; 4 cycles
dec delay0
; 4 cycles
bne u1
; 3 cycles
}
}
}
/* del1m - Delay about 1msec times the "d" argument */
void del1m(int d) {
while (d--) {
asm {
; The following code delays 1 millisecond by looping.
; Total time is 4 + 5 * (4 + 68 * (4 + 3) + 4 + 3) = 2439 cycles
; A 9.8304MHz external clock gives an internal CPU clock of
; 2.4576MHz (407ns/cycle). Delay is then .993 milliseconds.
mov #$5,delay1 ; 4 cycles
m1: mov #68,delay0 ; 4 cycles
m0: dec delay0
; 4 cycles
bne m0
; 3 cycles
dec delay1
; 4 cycles
bne m1
; 3 cycles
}
}
}
}
/**************************************** SCI Port
****************************************/
/**************************************** DELAY
****************************************/
/**************************************** TEST
****************************************/
/***************************************** DELAY
****************************************/
/* Note: these delay routines only work if the the delay0 and delay1
variables are located in the RAM zero page */
/* del40u - Delay about 40usec times the "d" argument */
void del40u(int d) {
while (d--) {
asm {
; The following code delays about 40 microseconds by looping.
; Total time is 4 + 13 * (4 + 3) = 95 cycles
; A 9.8304MHz external clock gives an internal CPU clock of
; 2.4576MHz (407ns/cycle). 95 x .407 usec = 38.7 usec.
; The JSR and RTS instructions will add a bit more.
void LCDMenu() {
del1m(100);
clearLCD();
while(one) {
if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
progMenuTime();
} //end if RIGHT
else if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
progMenuOutlets();
} //end if LEFT
else { //DISPLAY TIME
del1m(2);
strout(LCD_LINE1, (unsigned char *) strdurasaver);
del1m(2);
testCLK();
del1m(995);
strout(LCD_LINE2, (unsigned char *) str3); //"Dare to press another?"
} else if(UP) {
if(swDebounce) while(UP) {} //debounce - wait until button is released
clearLCD();
//cmdout(0x02); //cursor home
strout(LCD_LINE1, (unsigned char *) upstr); // "you pressed up!"
strout(LCD_LINE2, (unsigned char *) str3); //"Dare to press another?"
} else if(DOWN) {
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
clearLCD();
//cmdout(0x02); //cursor home
strout(LCD_LINE1, (unsigned char *) downstr); // "you pressed down!"
strout(LCD_LINE2, (unsigned char *) str3); //"Dare to press another?"
} else if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
clearLCD();
//cmdout(0x02); //cursor home
strout(LCD_LINE1, (unsigned char *) selectstr); // "you pressed select!"
strout(LCD_LINE2, (unsigned char *) str3); //"Dare to press another?"
} else { // do nothing
}
}
}
}
void testRemote() {
while(one) {
clearLCD();
if(checkManualOverride() == 1) {
strout(0, "manual override 1");
if(outlet[0] == 1) {
outlet[0] = 0;
OUTLET1 = 0;
strout(LCD_LINE2, "turn off");
del1m(thousand);
}
else if(outlet[0] == 0) {
outlet[0] = 1;
OUTLET1 = 1;
strout(LCD_LINE2, "turn on");
del1m(thousand);
}
}
}
}
/* Displays confirmation on the LCD of which button is pressed */
void testButtonsLCD() {
while(one) {
while(!LEFT && !RIGHT && !UP && !DOWN && !SELECT) testCLK();
if(LEFT) {
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
clearLCD();
//cmdout(0x02); //cursor home
strout(LCD_LINE1, (unsigned char *) leftstr); // "you pressed left!"
strout(LCD_LINE2, (unsigned char *) str3); //"Dare to press another?"
} else if(RIGHT) {
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
clearLCD();
//cmdout(0x02); //cursor home
strout(LCD_LINE1, (unsigned char *) rightstr); // "you pressed right!"
}
}
/* This program will test button function, output to an LED.
*
* LED: PTA0, output
* Left Button: LED blink 5x
* Right Button: LED blink 4x
* Up Button: LED blink 3x
* Down Button: LED blink 2x
* Select Button: LED blink 1x
*/
void testButtonsLED() {
PTA_PTA0 = 1; //LED off to start
while (1) { // Loop forever
if (LEFT) { //--> blink 5x
if(swDebounce) while(LEFT) {} //debounce - wait until button is released
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
}
else if(RIGHT) { //--> blink 4x
if(swDebounce) while(RIGHT) {} //debounce - wait until button is released
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
}
else if(UP) { // --> blink 3x
if(swDebounce) while(UP) {} //debounce - wait until button is released
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
}
else if(DOWN) { //--> blink 2x
if(swDebounce) while(DOWN) {} //debounce - wait until button is released
blink(thousand);
del1m(thousand);
blink(thousand);
del1m(thousand);
}
else if(SELECT) { //--> blink 1x
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
blink(thousand);
del1m(thousand);
}
else
PTA_PTA0 = 1; //off
}
}
void testI2Crap() {
//testCLK(); //do a read
strout(0, "before 2nd clkinit");
del1m(thousand);
clk_init();
strout(0, "woot woot");
//while(one) {
//testCLK();
//del1m(thousand);
//}
del1m(thousand);
programCLK();
}
void fakeLCD() {
unsigned char repeat = 1;
while(repeat) {
del1m(2);
strout(0, stroutlet);
del1m(2);
strout(0x40, "Outlet 1");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, stroutlet);
del1m(2);
strout(0x40, strexit);
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, strprogday);
del1m(2);
strout(0x40, "Sunday");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, stroffhour);
del1m(2);
strout(0x40, "08AM");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, stroffmin);
del1m(2);
strout(0x40, "08:30AM");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, stronhour);
del1m(2);
strout(0x40, "05PM");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
while(repeat) {
del1m(2);
strout(0, stronmin);
del1m(2);
strout(0x40, "05:20PM");
if(SELECT) {
if(swDebounce) while(SELECT) {} //debounce - wait until button is released
repeat = 0;
}
}
clearLCD();
repeat = 1;
}
teststr[11] = onmin[0];
teststr[12] = '0';
teststr[13] = onpm[0];
teststr[14] = 'M';
teststr[15] = '\0';
strout(0, teststr);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset],
1, THUSTART + addrOffset);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset], 1,
FRISTART + addrOffset);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset], 1,
SATSTART + addrOffset);
break;
} //end switch(today)
today = 1;
outletNum = 1;
regOffset = (outletNum - 1) * 2;
addrOffset = (regOffset >> 4) & 0x0f;
off10hr[0] = '0';
off09hr[0] = '9';
offpm[0] = '0';
offmin[0] = '0';
on10hr[0] = '0';
on09hr[0] = '6';
onpm[0] = '1';
onmin[0] = '3';
temp = ((((off10hr[outletNum - 1]*10) + off09hr[outletNum - 1]) & 0x0f) << 4) |
(((offmin[outletNum - 1] & 0x07) << 1) | (offpm[outletNum - 1] & 0x01)); //1001 0000 = 0x90
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset], 1,
SUNSTART + addrOffset);
break;
case '2': //Monday
clkRegs[MONREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset],
1, MONSTART + addrOffset);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset], 1,
TUESTART + addrOffset);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset],
1, WEDSTART + addrOffset);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset] = temp;
void testCLKRegs(void) {
unsigned char teststr[24];
unsigned char offset, i, temp, outletNum, today, regOffset, addrOffset;
today = 1;
outletNum = 1;
clkRegs[8] = 0x88;
clkRegs[9] = 0x77;
clkRegs[10] = 0x66;
clkRegs[11] = 0x55;
clkRegs[12] = 0x44;
clkRegs[13] = 0x33;
clkRegs[14] = 0x22;
clkRegs[15] = 0x11;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[8], 1, 0x08);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[9], 1, 0x09);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[10], 1, 0x0A);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[11], 1, 0x0B);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[12], 1, 0x0C);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[13], 1, 0x0D);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[14], 1, 0x0E);
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[15], 1, 0x0F);
del1m(1);
getDevData(1);
teststr[0] = off10hr[0];
teststr[1] = off09hr[0];
teststr[2] = ':';
teststr[3] = offmin[0];
teststr[4] = '0';
teststr[5] = onpm[0];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[0];
teststr[9] = on09hr[0];
teststr[10] = ':';
temp = ((((on10hr[outletNum - 1]*10) + on09hr[outletNum - 1]) & 0x0f) << 4) |
(((onmin[outletNum - 1] & 0x07) << 1) | (onpm[outletNum - 1] & 0x01)); //0110 0110 = 0x66
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset +
1], 1, SUNSTART + addrOffset + 0x01);
break;
case '2': //Monday
clkRegs[MONREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset +
1], 1, MONSTART + addrOffset + 0x01);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset +
1], 1, TUESTART + addrOffset + 0x01);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset +
1], 1, WEDSTART + addrOffset + 0x01);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset +
1], 1, THUSTART + addrOffset + 0x01);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset +
1], 1, FRISTART + addrOffset + 0x01);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset +
1], 1, SATSTART + addrOffset + 0x01);
break;
} //end switch(today)
del1m(1);
getDevData(1);
teststr[0] = off10hr[0];
teststr[1] = off09hr[0];
teststr[2] = ':';
teststr[3] = offmin[0];
teststr[4] = '0';
teststr[5] = onpm[0];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[0];
teststr[9] = on09hr[0];
teststr[10] = ':';
teststr[11] = onmin[0];
teststr[12] = '0';
teststr[13] = onpm[0];
teststr[14] = 'M';
teststr[15] = '\0';
strout(0x40, teststr);
del1m(5000);
clearLCD();
strout(0, teststr);
off10hr[0] = '1';
off09hr[0] = '2';
offpm[0] = '1';
offmin[0] = '2';
on10hr[0] = '1';
on09hr[0] = '0';
onpm[0] = '0';
onmin[0] = '4';
temp = ((((off10hr[outletNum - 1]*10) + off09hr[outletNum - 1]) & 0x0f) << 4) |
(((offmin[outletNum - 1] & 0x07) << 1) | (offpm[outletNum - 1] & 0x01)); //1001 0000 = 0x90
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset], 1,
SUNSTART + addrOffset);
break;
case '2': //Monday
clkRegs[MONREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset],
1, MONSTART + addrOffset);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset], 1,
TUESTART + addrOffset);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset],
1, WEDSTART + addrOffset);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset],
1, THUSTART + addrOffset);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset], 1,
FRISTART + addrOffset);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset], 1,
SATSTART + addrOffset);
break;
} //end switch(today)
temp = ((((on10hr[outletNum - 1]*10) + on09hr[outletNum - 1]) & 0x0f) << 4) |
(((onmin[outletNum - 1] & 0x07) << 1) | (onpm[outletNum - 1] & 0x01)); //0110 0110 = 0x66
switch(hexCode[today]) {
case '1': //Sunday
clkRegs[SUNREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SUNREG + regOffset +
1], 1, SUNSTART + addrOffset + 0x01);
break;
case '2': //Monday
clkRegs[MONREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[MONREG + regOffset +
1], 1, MONSTART + addrOffset + 0x01);
break;
case '3': //Tuesday
clkRegs[TUEREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[TUEREG + regOffset +
1], 1, TUESTART + addrOffset + 0x01);
break;
case '4': //Wednesday
clkRegs[WEDREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[WEDREG + regOffset +
1], 1, WEDSTART + addrOffset + 0x01);
break;
case '5': //Thursday
clkRegs[THUREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[THUREG + regOffset +
1], 1, THUSTART + addrOffset + 0x01);
break;
case '6': //Friday
clkRegs[FRIREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[FRIREG + regOffset +
1], 1, FRISTART + addrOffset + 0x01);
break;
case '7': //Saturday
clkRegs[SATREG + regOffset + 1] = temp;
i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[SATREG + regOffset +
1], 1, SATSTART + addrOffset + 0x01);
break;
} //end switch(today)
teststr[7] = ' ';
teststr[8] = on10hr[0];
teststr[9] = on09hr[0];
teststr[10] = ':';
teststr[11] = onmin[0];
teststr[12] = '0';
teststr[13] = onpm[0];
teststr[14] = 'M';
teststr[15] = '\0';
strout(0x40, teststr);
del1m(5000);
del1m(1);
//i2c_read2(CLOCK_RD_ADDR, dayData, 8, 0x08);
getDevData(1);
teststr[0] = hexCode[(dayData[0] >> 4) & 0x0f];
teststr[1] = hexCode[(dayData[0]) & 0x0f];
teststr[2] = hexCode[(dayData[1] >> 4) & 0x0f];
teststr[3] = hexCode[(dayData[1]) & 0x0f];
teststr[4] = hexCode[(dayData[2] >> 4) & 0x0f];
teststr[5] = hexCode[(dayData[2]) & 0x0f];
teststr[6] = hexCode[(dayData[3] >> 4) & 0x0f];
teststr[7] = hexCode[(dayData[3]) & 0x0f];
teststr[8] = hexCode[(dayData[4] >> 4) & 0x0f];
teststr[9] = hexCode[(dayData[4]) & 0x0f];
teststr[10] = hexCode[(dayData[5] >> 4) & 0x0f];
teststr[11] = hexCode[(dayData[5]) & 0x0f];
teststr[12] = hexCode[(dayData[6] >> 4) & 0x0f];
teststr[13] = hexCode[(dayData[6]) & 0x0f];
teststr[14] = hexCode[(dayData[7] >> 4) & 0x0f];
teststr[15] = hexCode[(dayData[7]) & 0x0f];
teststr[16] = '\0';
//strout(0, teststr);
del1m(1);
getDevData(1);
teststr[0] = off10hr[0];
teststr[1] = off09hr[0];
teststr[2] = ':';
teststr[3] = offmin[0];
teststr[4] = '0';
teststr[5] = onpm[0];
teststr[6] = 'M';
//clkRegs[8] = 0xA4; //0001 001 0 = 1:10am, 1010 010 0 = A4 = 10:20am
//clkRegs[9] = 0xC9; //0010 010 1 = 2:20pm, 1100 100 1 = C9 = 12:40pm
//i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[8], 1, 0x08);
//i2c_write2(CLOCK_WR_ADDR, (unsigned char *) &clkRegs[9], 1, 0x09);
del1m(1);
//i2c_read2(CLOCK_RD_ADDR, dayData, 8, SUNSTART);
getDevData(1);
else if(hexCode[(dayData[offset+1] & 0x01)] == '1')
onpm[i-1] = 'P';
else
onpm[i-1] = '?';
i = 1;
offset = (i - 1) * 2; //index offset for dayData, based on device #
//e.g. dev 4 is stored at 6 and 7 (4 - 1 = 3 * 2 = 6)
// (2a) process "off" time
if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'A') {
off10hr[i-1] = '1';
off09hr[i-1] = '0';
} else if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'B') {
off10hr[i-1] = '1';
off09hr[i-1] = '1';
} else if(hexCode[((dayData[offset] >> 4) & 0x0f)] == 'C') {
off10hr[i-1] = '1';
off09hr[i-1] = '2';
} else {
off10hr[i-1] = '0';
off09hr[i-1] = hexCode[(dayData[offset] >> 4) & 0x0f]; //up to 9
}
offmin[i-1] = hexCode[(dayData[offset] & 0x0e) >> 1]; //all but last bit (bits 3-1)
if(hexCode[(dayData[offset] & 0x01)] == '0') //last bit is am/pm
offpm[i-1] = 'A';
else if(hexCode[(dayData[offset] & 0x01)] == '1')
offpm[i-1] = 'P';
else
offpm[i-1] = '?';
// (2b) process "on" time
if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'A') {
on10hr[i-1] = '1';
on09hr[i-1] = '0';
} else if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'B') {
on10hr[i-1] = '1';
on09hr[i-1] = '1';
} else if(hexCode[((dayData[offset+1] >> 4) & 0x0f)] == 'C') {
on10hr[i-1] = '1';
on09hr[i-1] = '2';
} else {
on10hr[i-1] = '0';
on09hr[i-1] = hexCode[(dayData[offset+1] >> 4) & 0x0f]; //up to 9
}
onmin[i-1] = hexCode[(dayData[offset+1] & 0x0e) >> 1]; //all but last bit (bits 3-1)
if(hexCode[(dayData[offset+1] & 0x01)] == '0') //last bit is am/pm
onpm[i-1] = 'A';
teststr[0] = off10hr[0];
teststr[1] = off09hr[0];
teststr[2] = ':';
teststr[3] = offmin[0];
teststr[4] = '0';
teststr[5] = onpm[0];
teststr[6] = 'M';
teststr[7] = ' ';
teststr[8] = on10hr[0];
teststr[9] = on09hr[0];
teststr[10] = ':';
teststr[11] = onmin[0];
teststr[12] = '0';
teststr[13] = onpm[0];
teststr[14] = 'M';
teststr[15] = '\0';
//strout(0x40, teststr);
//del1m(5000);
}
void testOutlets() {
del1m(2);
DDRB_DDRB0 = 1;
DDRB_DDRB1 = 1;
DDRB_DDRB2 = 1;
DDRB_DDRB3 = 1;
while(one) {
OUTLET1 = 1;
strout(0, "outlet 1");
del1m(thousand);
OUTLET1 = 0;
OUTLET2 = 1;
strout(0, "outlet 2");
del1m(thousand);
OUTLET2 = 0;
}
strout(0, "manov 2!");
break;
OUTLET3 = 1;
strout(0, "outlet 3");
del1m(thousand);
OUTLET3 = 0;
case 3:
blink(1000);
blink(1000);
blink(1000);
if(outlet[2] == 1) {
outlet[2] = OUTLET3 = 0;
}
else if(outlet[2] == 0) {
outlet[2] = OUTLET3 = 1;
}
strout(0, "manov 3!");
break;
OUTLET4 = 1;
strout(0, "outlet 4");
del1m(thousand);
OUTLET4 = 0;
}
}
/* turn on LED in port A bit 0 for n msec, then turn off */
void blink(int n) {
PTA_PTA0 = 0; //turn on LED
del1m(n); //leave on n msec
PTA_PTA0 = 1; //turn off LED
}
/* test manual override */
void testManOv() {
while(one) {
switch(checkManualOverride()) {
case 1:
blink(1000);
if(outlet[0] == 1) {
outlet[0] = OUTLET1 = 0;
}
else if(outlet[0] == 0) {
outlet[0] = OUTLET1 = 1;
}
strout(0, "manov 1!");
break;
case 2:
blink(1000);
blink(1000);
if(outlet[1] == 1) {
outlet[1] = OUTLET2 = 0;
}
else if(outlet[1] == 0) {
outlet[1] = OUTLET2 = 1;
case 4:
blink(1000);
blink(1000);
blink(1000);
blink(1000);
if(outlet[3] == 1) {
outlet[3] = OUTLET4 = 0;
}
else if(outlet[3] == 0) {
outlet[3] = OUTLET4 = 1;
}
strout(0, "manov 4!");
break;
default:
del1m(2);
strout(0, strdurasaver);
testCLK();
del1m(1000);
} //end switch
} //end while(one)
}
/**************************************** TEST
****************************************/
Appendix C
Parts List
and
Cost Analysis
Parts Lists and Cost Analysis
Main Module
- Prototype
Supplier
Digikey
Part Number
MC908JL16CPEND
Digikey
10KH-ND
Digikey
1.0KH-ND
Digikey
330H-ND
Digikey
Digikey
Digikey
470H-ND
67-1071-ND
67-1063-ND
Digikey
P1363-ND
Digikey
493-1808-ND
Digikey
478-2475-ND
Digikey
490-3775-ND
Digikey
401-1963-ND
Digikey
BG Micro
296-1643-5-ND
LCD1029
SparkFun
WRL-08947
Digikey
X114-ND
Digikey
Digikey
DS1307+-ND
DS32KHZ/DIPND
Digikey
Digikey
1N4148DICT-ND
2N3904FS-ND
Digikey
HE100-ND
Digikey
Digikey
Digikey
A98060-ND
P138-ND
BU2032-1-HD-GND
Digikey
T977-P6P-ND
Total Cost
Price Each
(Bulk,
>1,000)
Cost
(Per
Unit)
Quantity
Price Each
(Individual)
1
$3.23
$1.86
$3.23
$1.86
13
$0.06
$0.01
$0.78
$0.13
4
$0.06
$0.01
$0.24
$0.04
5
$0.06
$0.01
$0.30
$0.05
5
1
4
$0.06
$0.12
$0.09
$0.01
$0.08
$0.06
$0.30
$0.12
$0.36
$0.05
$0.08
$0.24
1
$0.89
$0.28
$0.89
$0.28
5
$0.18
$0.04
$0.90
$0.20
5
$0.27
$0.08
$1.35
$0.40
5
$0.25
$0.08
$1.25
$0.40
6
$0.99
$0.43
$5.94
$2.58
1
1
$0.43
$3.95
$0.14
$3.95
$0.43
$3.95
$0.14
$3.95
1
$5.95
$4.76
$5.95
$4.76
1
$1.88
$1.05
$1.88
$1.05
1
$3.74
$1.66
$3.74
$1.66
1
$5.46
$5.46
$5.46
$5.46
4
4
$0.02
$0.11
$0.02
$0.02
$0.08
$0.44
$0.08
$0.08
4
$1.50
$0.60
$6.00
$2.40
5
1
$2.25
$0.38
$1.35
$0.23
$11.25
$0.38
$6.75
$0.23
Battery Holder
1
$0.63
$0.45
$0.63
$0.45
Power Supply
1
$7.16
$4.77
$7.16
$4.77
$63.01
$38.09
Description
MC908JL16
uC
Resistor - 10
kOhm
Resistor - 1
kOhm
Resistor - 330
Ohm
Resistor - 470
Ohm
LED - Red
LED - Green
Capacitor 10uF
Capacitor 4.7uF
Capacitor 0.22uF
Capacitor 0.01uF
Pushbutton
SPST
Hex SchmittTrigger
Inverter
24x2 LCD
RF Receiver 315 MHz
10 MHz
Crystal
Oscillator
Real-Time
Clock
32kHz
Oscillator
Diode 1N4148
NPN BJT
Relay SPSTNO
Terminal Block
- Wire to Board
Battery - 3V
Cost (Bulk,
>1,000 Units)
Remote
Control Prototype
Supplier
Digikey
Part Number
MC908JL16CPEND
Digikey
10KH-ND
Digikey
401-1963-ND
Jameco
321736
Digikey
X114-ND
SparkFun
WRL-08945
Digikey
P145-ND
Digikey
BH9V-W-ND
Digikey
67-1898-ND
Description
MC908JL16
uC
Resistor - 10
kOhm
Pushbutton
SPST
Push-Button
Debouncer
10 MHz
Crystal
Oscillator
RF
Transmitter 315 MHz
Quantity
Battery - 9V
Battery
Holder
Toggle
Switch SPST
Price Each
(Individual)
Price Each
(Bulk,
>1,000)
Cost
(Per
Unit)
Cost (Bulk,
>1,000 Units)
1
$3.23
$1.86
$3.23
$1.86
5
$0.06
$0.01
$0.30
$0.05
5
$0.99
$0.43
$4.95
$2.15
1
$5.99
$3.82
$5.99
$3.82
1
$1.88
$1.05
$1.88
$1.05
1
$3.95
$3.16
$3.95
$3.16
1
$2.31
$1.00
$2.31
$1.00
1
$0.86
$0.62
$0.86
$0.62
1
$3.48
$1.54
$3.48
$1.54
$26.95
$15.25
Total Cost
Complete Product (Prototype)
Item
Cost (Per Unit)
Cost (Bulk, >1,000 Units)
Main Module
$63.01
$38.09
Remote Control
$26.95
$15.25
Total Cost
$89.96
$53.34
Main
Module
PCB
Supplier
Digikey
Part Number
MC908JL16CDWEND
Digikey
P10KETR-ND
Digikey
P1.0KETR-ND
Digikey
P330ETR-ND
Digikey
Digikey
Digikey
P470ETR-ND
67-1071-ND
67-1063-ND
Digikey
PCE3757CT-ND
Digikey
PCE3021DKR-ND
Digikey
PCE1012TR-ND
Digikey
445-2494-2-ND
Digikey
147873-1-ND
Digikey
BG Micro
296-1212-5-ND
LCD1029
SparkFun
WRL-08947
Digikey
SE2818TR-ND
Digikey
DS1307Z+-ND
Digikey
Digikey
Digikey
DS32KHZS#-ND
1N4148WTDITR-ND
2N3904FS-ND
Digikey
374-1039-2-ND
Digikey
Digikey
Digikey
Total Cost
1776226-1-ND
P022-ND
T977-P6P-ND
Description
MC908JL16 uC
Resistor - 10
kOhm
Resistor - 1
kOhm
Resistor - 330
Ohm
Resistor - 470
Ohm
LED - Red
LED - Green
Capacitor 10uF
Capacitor 4.7uF
Capacitor 0.22uF
Capacitor 0.01uF
Pushbutton
SPST
Hex SchmittTrigger Inverter
24x2 LCD
RF Receiver 315 MHz
10 MHz Crystal
Oscillator
Real-Time
Clock
32kHz
Oscillator
Diode - 1N4148
NPN BJT
Relay SPSTNO
Terminal Block
- Wire to Board
Battery - 3V
Power Supply
Quantity
Price Each
(Bulk,
>10,000)
Cost to Product
(Bulk, >10,000
Units)
1
$1.74
$1.74
13
$0.01
$0.10
4
$0.01
$0.03
5
$0.01
$0.04
5
1
4
$0.01
$0.06
$0.06
$0.04
$0.06
$0.25
1
$0.14
$0.14
5
$0.12
$0.61
5
$0.16
$0.80
5
$0.03
$0.14
6
$0.11
$0.68
1
1
$0.15
$3.95
$0.15
$3.95
1
$4.76
$4.76
1
$1.56
$1.56
1
$1.66
$1.66
1
4
4
$3.29
$0.08
$0.02
$3.29
$0.31
$0.08
4
$3.09
$12.35
5
1
1
$0.50
$0.98
$4.77
$2.48
$0.98
$4.77
$40.94
Remote
Control
PCB
Supplier
Digikey
Part Number
MC908JL16CDW
E-ND
Digikey
P10KETR-ND
Digikey
147873-1-ND
Elab
EDE2008SO
Digikey
SE2818TR-ND
SparkFun
Digikey
Digikey
WRL-08945
P145-ND
1294K-ND
Digikey
CKN9049TR-ND
Quantit
y
Description
MC908JL16 uC
Resistor - 10
kOhm
Pushbutton
SPST
Push-Button
Debouncer
10 MHz Crystal
Oscillator
RF Transmitter
- 315 MHz
Battery - 9V
Battery Holder
Toggle Switch
SPST
Price Each
(Bulk,
>10,000)
Cost to Product
(Bulk, >10,000
Units)
1
$1.74
$1.74
5
$0.01
$0.04
5
$0.11
$0.56
1
$2.35
$2.35
1
$1.56
$1.56
1
1
1
$3.16
$0.92
$0.74
$3.16
$0.92
$0.74
1
$2.64
$2.64
Total Cost
$13.71
Complete Product PCB
Item
Cost (Bulk, >10,000 Units)
Main Module
$40.94
Remote Control
$13.71
Total Cost
$54.66
Download