

/*
col_pic copyright (c) 2009-always Jan Panteltje

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


col_pic is an X11 program intended to work with PIC based
hardware to drive 3 LEDs, red, green, and blue, to create a controlled color lighting.
It sends color commands via a serial port.

col.hex communicates at 19200 Baud, 8 data bits, 1 stop bit, no hardware handshaking.

Commands recognised by col.hex:
BnnnLF              set blue PWM, range 0-255.
CnnnENTER           set clock calibration, range 0-255, saved in EEPROM
c                   prints clock speed.
D                   set clock prescaler1 and clock speed defaults, deselect fast mode.
FnnnENTER           set clock prescaler, range 0-255, default 255, saved in EEPROM.
f                   print clock prescaler.
GnnnLF              set green PWM, range 0-255.
HnnENTER            set hour, range 0-23
LnnENTER            set light sensitivity (0-31), default 0, saved in EEPROM.
l                   print light sensitivity, light comparator status (on or off), and actual measured light level (0-31) where 0 is brightest and 31 is dark.
MnnENTER            set minute, range 0-59.
PnENTER             program timer number n, n is range 0-4. will ask for hour, minute, red, green, blue, timers saved in EEPROM.
p                   display timers, sorted, timer_nr, hour, minute, red, green, blue 
RnnnLF              set red PWM, range 0-255.
S                   save settings in EEPROM.
s                   sends back R, G, B in the form of 3 integers.
t                   prints time
X                   set fast mode, save in EEPROM.
x                   reset fast mode, saved in EERPOM.
ENTER stands for code 10 (LF) or code 13(CR). 


Programming the PIC 16F648A:
You need a hex programmer, use the file col.hex

Assembling col.hex (if you are into that),
col.asm was assembled with gpasm-0.13.5 beta
To assemble col.asm type:
./make_asm


Connecting the PIC 16F648A

The following values give approximately white for my LEDs with all 3 colors at 255, use trimpots in blue and red, green as reference: 
Red LED pin 18 via a 220 Ohm resistor to +5V. 
Green LED pin 17 via a 100 Ohm resistor to +5V. 
Blue LED pin 16 via a 1000 Ohm resistor to +5V. 

Ground to pin 5.
+5V to pin 14.

RX data (via for example a MAX232 chip) to pin 7.
TX data (via for example a MAX232 chip) to pin 8.

Thats is all. 


You need:
xforms installed, and the forms.h header file.

See INSTALL for install instructions.



User interface:

1) Color selection.
There are 2 color selection interfaces.
The left one allows you to select a color from the rgb database in /usr/lib/X11/rgb.txt
by clicking on a browser entry.
You an also move the vertical sliders in the middle, color will then snap to the nearest
entry in the table.
The selected color is displayed in the square box above the vertical color selection sliders.

The right hand interface allows you to select a color by turning the arrow in the color wheel.
You can set saturation with the saturation slider, and brightness with the brightness slider.
The selected color, saturation, and brightness is displays in the color circle,
also the angle representing the color is displayed below the color circle.

Both color selection methods have there limitations, use whatever gets you the color you want.


2) Database button.
By pressing the wide button below the color browser you can select an other color database name.
I have provided a sorted lowercase version of the rgb.txt as rgb_lowercase_sorted.txt.


3) Gamma button.
Gamma correction and driving RGB color LEDs with PWM from a color table. 

When we have a PWM system driving red, green, and blue LEDs, 
and use a color table to select the color, as I do for example here, 
then that color table *normally* is used to set the DAC in the graphics card. 

That DAC creates a voltage that is send to the CRT, and the CRT 
has a function of brightness versus drive voltage of y = x ^2.2. 
In LCD monitors this function is created in the firmware to be compatible to 
CRT monitors. 

So, it is safe to assume that in color tables, as in for example in Linux in 
/usr/lib/X11/rgb.txt, the gamma is already corrected to the opposite curve: 
y = x^(1/2.2), so that it looks correct on a CRT or LCD monitor. 

So, to use these tables, we need to mimic a CRT curve, and correct 
the 0-255 values with y = x^(2.2).
This is why I added the gamma button.
You can select a different value for gamma by pressing the gamma button, or disable gamma
correction by pressing the 'gamma on' button.


4) Serial device select button:
You can select a different serial device name by pressing this button.


5) Save settings button.
Pressing this button will send the 'S' command to the PIC hardware and the PIC hardware will then
store the current selected intensity for red, green, and blue in EEPROM, so that
on a next power on the PIC hardware will display the same color, even without a PC connected.

 
6) Exit button.
Pressing this button will exit col_pic.
All settings are always saved when controls are activated, so that if you restart col_pic then
you will be at the same point.



The PIC side:


Clock:
The clock is a 24 hours clock, display is in hours and minutes.
You can set the actual time with 'H' for minute, and 'M' for hour, and see the time by typing 't'.

Clock speed:
Typing 'D' sets the default values for the clock prescaler and clock speed variables.
As the PIC uses the internal 4MHz oscillator, its speed may vary a bit.
You can change the clock speed by changing the prescaler with 'F',
and the speed with 'C', values are saved in EEEPROM.
'f' and 'c' show the settings.
So, if the clock is slow, decrease the value in c and / or f, else increase it.

Timers:
Typing 'P' will ask for a timer number, enter 0, 1, 2, 3, or 4, then ENTER.
It then asks for hour, minute, red, green and blue.
Enter the digits, and then ENTER.
After entering the value for blue, the timers are saved t oEEPROM, and displayed like this:
0 0:0 255 0 0  1 2:0 200 100 50  2 4:0 120 0 120  3 7:0 0 255 10  4 12:0 30 70 150
this says that timer 0 starts at 0:0h (midnight), and sets red to 255, green to 0, and blue to 0.
timer 1 starts at 2:0h, and sets red to 200, green to 100, and blue to 50.
etc.
If you want to disable a timer, enter 255 for hour and minute, any value for the color.
Timers are disabled by default (the EEPROM contains 255 in all locations after programming).

Fast mode:
Typing 'X' will enter fast mode, typing 'x' will go back to normal mode.
When in fast mode, the clock speeds up incredibly, cycling through 24 hours in seconds,
minutes  will always be zero.
This can be used in combination with the timers to flash different colors.
When setting a timer for use in fast mode, select the hour, and set minute to zero.

Light sensor:
A CdS cell senses light level.
If the light intensity drops that set with the 'L' command, the LEDs are enabled.
You can set light sensitivity with command 'L' from 0-31 , where 31 most sensitive.
Setting 0 always enables the LEDs.
Setting 31 will only enable the LEDs in total darkness.
This can be used to automatically switch the LEDs on when it gets dark, or the main lighting goes off.
Try 15.
The 'l' command shows the value set by 'L', the LEDs state 'on' or 'off' and the actual light sensor output (0-31),
where 0 is brightest, and 31 is darkest.

Scripting:
It is possible to use the col.hex with a simple terminal program, and / or to change color over time from a script for example. 
ptlrc-0.3.tgz  is a simple terminal program (Linux) that by default will work with col.hex, and also can be called from a script: 

Here an example how to call ptlrc from a script, it sets red to 30, green to 20, blue to 10, and display the status of the registers in the PIC, then returns: 
echo -e "R30\nG20\nB10\ns" | ptlrc -i 
You can use crontab to change colors on certain times during the day: 
Make a copy of the current crontab: 
crontab -l > ~/crtab 
Edit crtab like this: 
49 15 * * * /bin/echo -en "R255\nG255\nB255\ns" | /usr/local/bin/ptlrc -i 1>/dev/zero 2>/dev/zero 
50 15 * * * /bin/echo -en "R255\nG55\nB5\ns" | /usr/local/bin/ptlrc -i 1>/dev/zero 2>/dev/zero 
51 15 * * * /bin/echo -en "R5\nG55\nB255\ns" | /usr/local/bin/ptlrc -i 1>/dev/zero 2>/dev/zero 

This will set red, green, and blue to maximum at 15:49, to 255, 55, 5 at 15:50, and to 5, 55, 255 at 15:51. 
Make the new entry active: 
crontab ~/crtab 
You can list crontab with: 
crontab -l 
crond must be running for this to work. 
So now you can even simulate a rising sun in your bedroom to wake you up, have special sphere light in the evening too, all automagically.

