# Understanding code and "routines"

I am working on the "phi clock V5" code.

It is 90% what I need/want. Well, nominally 90%. Suffice to say it is nearly there.

I have an Ether10 card, shall have the Phi-2 shield, and the 20x4 display. There will be an RTC on the Phi-2 shield. (More to come)

Where I am falling down a bit is reading the code and understanding where/how the pins are defined.

Ok, I a haven't read EVERY page of the code cover to cover, but it is a bit confusing.

I am liasing with Liudr, and I am not saying he isn't helping, but he is doing exams just now so I don't want to annoy him too much.

I feel if I say more, I'll make a bigger fool of myself than I am already am. So I'll see if anyone can help me get my head around it.

It is also a bit difficult for me just now as I stil don't have all the hardware, so can't "try and see what happens".

Where I am falling down a bit is reading the code

You use the definite article there, but I don't see any code.

Where I am falling down a bit is reading the code

Me too, I can't read a single line of it!

Oh, I didn’t post the code as it is so well mentioned here I thought it would be redundant.

Ok, here is the code:

(I hope)

/*
Phi-2 shield for Arduino
Program title: Phi clock version 5
----------------------------------------
Instructions:
0. Please download phi_interfaces library (http://liudr.wordpress.com/phi_interfaces/) and unzip the files and example subfolders in arduino\sketchbooks\libraries\phi_interfaces\
1. Please download phi_prompt library (http://liudr.wordpress.com/phi_prompt/) and unzip the files and example subfolders in arduino\sketchbooks\libraries\phi_prompt\
2. Please download phi_big_font library (http://liudr.wordpress.com/phi_big_font/) and unzip the three files and example subfolders in arduino\sketchbooks\libraries\phi_big_font\
3. Please set the size of you display with "#define lcd_rows" and "#define lcd_columns" so the program will automatically adjust to your display size.
4. You need to set the clock before you can use it. Uncomment this line "#define setRTC" among the #define lines.
5. Update the time in setup() to the current time.
6. Upload the sketch to arduino to set the time.
7. Then comment the line "#define setRTC" and recompile and upload to arduino.
8. If you don't do step 4, the clock will be reset every time arduino resets.
----------------------------------------
Programmed by Dr. John Liu
Revision: 02/28/2012
Free software for educational and personal uses.
No warrantee!
Commercial use without authorization is prohibited.
Find details of the Phi-1 shield, Phi-2 shield, and Phi-prompt or contact Dr. Liu at
http://liudr.wordpress.com/phi-1-shield/
http://liudr.wordpress.com/phi-2-shield/
http://liudr.wordpress.com/phi_interfaces/
http://liudr.wordpress.com/phi_prompt/
All rights reserved.
----------------------------------------
List of functions:
* Display real time clock with Year month, date, day of week, hour, minute, and second.
* Four individual alarms (change Max_alarms to get more alarms)
* Alarms are stored on Arduino EEPROM and won't be lost when the power is out.
* Alarms Daily, Weekday, Weekend, Once, Off.
* Adjustable alarms. Press B to choose alarm and adjust the time.
* Adjustable clock and date. Press A to adjust clock and date.
* TODO - Add snooze function.
* TODO - Add special function on the alarm to drive outputs other than the buzzer and LED. You can be creative!
----------------------------------------
Thanks:

RTC created by matt.joyce@gmail.com

EEPROM Author: hkhijhe

Dependent libraries:
Phi_prompt version 1.0
Phi_interfaces version 1.0
Phi_big_font version 1.0

*/
#define phi_2_shield
#include <LiquidCrystal.h>
#include <Wire.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <EEPROM.h>
#include <phi_interfaces.h>
#include <phi_prompt.h>
#include <phi_big_font.h>
#include "DS1307_1.h"
#include "alarm_clock.h"

#define lcd_rows 2
#define lcd_columns 16
//#define setRTC
//Phi-2 shield definitions

//Phi-2 shield buttons and channel pin assignments
#define buzzer 16
#define total_buttons 6
#define btn_u 5
#define btn_d 10
#define btn_l 11
#define btn_r 4
#define btn_b 14
#define btn_a 15

//Phi-2 shield LCD pin setting
#define LCD_RS 8
#define LCD_EN 9
#define LCD_D4 7
#define LCD_D5 6
#define LCD_D6 2
#define LCD_D7 3

#define alarm_EEPROM_storage 1023-3*Max_alarms // Where the alarm is saved.

PROGMEM prog_char msg_00[]="LCD ALARM CLOCK\nDeveloped by:\nDr.Liu 02/28/12\nhttp://liudr.wordpress.com";


(more to come)

Moderator edit: CODE TAGS

I have also printed out some/all/most of the other libraries needed.

PROGMEM prog_char month_00[]="JAN";
PROGMEM prog_char month_01[]="FEB";
PROGMEM prog_char month_02[]="MAR";
PROGMEM prog_char month_03[]="APR";
PROGMEM prog_char month_04[]="MAY";
PROGMEM prog_char month_05[]="JUN";
PROGMEM prog_char month_06[]="JUL";
PROGMEM prog_char month_07[]="AUG";
PROGMEM prog_char month_08[]="SEP";
PROGMEM prog_char month_09[]="OCT";
PROGMEM prog_char month_10[]="NOV";
PROGMEM prog_char month_11[]="DEC";
PROGMEM const char *month_items[]= {month_00,month_01,month_02,month_03,month_04,month_05,month_06,month_07,month_08,month_09,month_10,month_11};

PROGMEM prog_char dow_00[]="SUN";
PROGMEM prog_char dow_01[]="MON";
PROGMEM prog_char dow_02[]="TUE";
PROGMEM prog_char dow_03[]="WED";
PROGMEM prog_char dow_04[]="THU";
PROGMEM prog_char dow_05[]="FRI";
PROGMEM prog_char dow_06[]="SAT";
PROGMEM const char *dow_items[]= {dow_00,dow_01,dow_02,dow_03,dow_04,dow_05,dow_06};

PROGMEM prog_char alarm_00[]="Off";
PROGMEM prog_char alarm_01[]="Daily";
PROGMEM prog_char alarm_02[]="Weekday";
PROGMEM prog_char alarm_03[]="Weekend";
PROGMEM prog_char alarm_04[]="Once";
PROGMEM const char *alarm_items[]= {alarm_00,alarm_01,alarm_02,alarm_03,alarm_04};

PROGMEM prog_char lcd_chr0[]={64,64,64,64,64,64,64,64,0};// 0
PROGMEM prog_char lcd_chr1[]={64,64,64,64,64,31,31,31,0};//1
PROGMEM prog_char lcd_chr2[]={64,64,64,31,31,64,64,64,0};//2
PROGMEM prog_char lcd_chr3[]={64,64,64,31,31,31,31,31,0};//3 {64,64,64,31,31,64,31,31,0};
PROGMEM prog_char lcd_chr4[]={31,31,31,64,64,64,64,64,0};//4
PROGMEM prog_char lcd_chr5[]={31,31,64,64,64,31,31,31,0};//5
PROGMEM prog_char lcd_chr6[]={31,31,31,31,31,64,64,64,0};//6 {31,31,64,31,31,64,64,64,0}
PROGMEM prog_char lcd_chr7[]={31,31,31,31,31,31,31,31,0};//7 {31,31,64,31,31,64,31,31,0}
PROGMEM const char *chr_item[] = {lcd_chr0, lcd_chr1, lcd_chr2, lcd_chr3, lcd_chr4, lcd_chr5, lcd_chr6, lcd_chr7};// The following lines instantiates a button group to control 6 buttons

byte pins[]={btn_u,btn_d,btn_l,btn_r,btn_b,btn_a}; // The digital pins connected to the 6 buttons.
char mapping[]={'U','D','L','R','B','A'}; // This is a list of names for each button.
phi_button_groups my_btns(mapping, pins, total_buttons);

// This serial keypad is for debugging.
phi_serial_keypads debug_keypad(&Serial,115200);

// The following sets up function keys for phi_prompt library
char up_keys[]={"U"}; ///< All keys that act as the up key are listed here.
char down_keys[]={"D"}; ///< All keys that act as the down key are listed here.
char left_keys[]={"L"}; ///< All keys that act as the left key are listed here.
char right_keys[]={"R"}; ///< All keys that act as the right key are listed here.
char enter_keys[]={"B"}; ///< All keys that act as the enter key are listed here.
char escape_keys[]={"A"}; ///< All keys that act as the escape key are listed here.
char * function_keys[]={up_keys,down_keys,left_keys,right_keys,enter_keys,escape_keys}; ///< All function key names are gathered here fhr phi_prompt.

// The following adds all available keypads as inputs for phi_prompt library
multiple_button_input * keypads[]={&my_btns,&debug_keypad,0};

LiquidCrystal lcd(LCD_RS,LCD_EN,LCD_D4,LCD_D5,LCD_D6,LCD_D7); // Create the lcd object

int rtc[7];
DS1307 RTC=DS1307(); // Create RTC object
alarm_clock clock1(false); // Create an alarm clock

void setup()
{
byte ch_buffer[10]; // This buffer is required for custom characters on the LCD.
lcd.begin(lcd_columns, lcd_rows);
Wire.begin(); // initialize wire
init_phi_prompt(&lcd,keypads,function_keys, lcd_columns, lcd_rows, '~'); // Supply the liquid crystal object, input keypads, and function key names. Also supply the column and row of the lcd, and indicator as '>'. You can also use '\x7e', which is a right arrow.
init_big_font(&lcd);

// Set the two channels to output to drive the buzzer and LED.
pinMode(buzzer,OUTPUT);
digitalWrite(buzzer,LOW);

#ifdef setRTC
// Set/init RTC
RTC.stop();
RTC.set(DS1307_SEC,0);
RTC.set(DS1307_MIN,50);
RTC.set(DS1307_HR,0);
RTC.set(DS1307_DOW,3); // value from 1 to 7. User define whether 1 is sun or mon.
RTC.set(DS1307_DATE,16);
RTC.set(DS1307_MTH,11);
RTC.set(DS1307_YR,10);
RTC.start();

//Set alarms
EEPROM.write(alarm_EEPROM_storage,6); // Alarm 0 hour
EEPROM.write(alarm_EEPROM_storage+1,50); // Alarm 0 minute
EEPROM.write(alarm_EEPROM_storage+2,2); // Alarm 0 frequency M-F

EEPROM.write(alarm_EEPROM_storage+3,7); // Alarm 1 hour
EEPROM.write(alarm_EEPROM_storage+4,00); // Alarm 1 minute
EEPROM.write(alarm_EEPROM_storage+5,2); // Alarm 1 frequency M-F

EEPROM.write(alarm_EEPROM_storage+6,7); // Alarm 2 hour
EEPROM.write(alarm_EEPROM_storage+7,10); // Alarm 2 minute
EEPROM.write(alarm_EEPROM_storage+8,2); // Alarm 2 frequency M-F

EEPROM.write(alarm_EEPROM_storage+9,9); // Alarm 3 hour
EEPROM.write(alarm_EEPROM_storage+10,30); // Alarm 3 minute
EEPROM.write(alarm_EEPROM_storage+11,3); // Alarm 3 frequency Weekend
#else
// Set alarm on the clock from EEPROM.
clock1.set_alarm(0, EEPROM.read(alarm_EEPROM_storage), EEPROM.read(alarm_EEPROM_storage+1), EEPROM.read(alarm_EEPROM_storage+2));
clock1.set_alarm(1, EEPROM.read(alarm_EEPROM_storage+3), EEPROM.read(alarm_EEPROM_storage+4), EEPROM.read(alarm_EEPROM_storage+5));
clock1.set_alarm(2, EEPROM.read(alarm_EEPROM_storage+6), EEPROM.read(alarm_EEPROM_storage+7), EEPROM.read(alarm_EEPROM_storage+8));
clock1.set_alarm(3, EEPROM.read(alarm_EEPROM_storage+9), EEPROM.read(alarm_EEPROM_storage+10), EEPROM.read(alarm_EEPROM_storage+11));
#endif

show_credit();
}

void loop()
{
top_menu(); // See Example_menu.pde
}

void show_credit()
{
// Display credits
phi_prompt_struct myLongMsg;

lcd.clear();
lcd.noBlink();
myLongMsg.ptr.msg_P=msg_00; // Assign the address of the text string to the pointer.
myLongMsg.low.i=0; // Default text starting position. 0 is highly recommended.
myLongMsg.high.i=strlen_P(msg_00); // Position of the last character in the text string, which is size of the string - 1.
myLongMsg.step.c_arr[0]=lcd_rows; // rows to auto fit entire screen
myLongMsg.step.c_arr[1]=lcd_columns; // one col list
myLongMsg.col=0; // Display the text area starting at column 0
myLongMsg.row=0; // Display the text area starting at row 0
myLongMsg.option=0; // Option 0, display classic message, option 1, display message with scroll bar on right.

text_area_P(&myLongMsg);
}


so well mentioned here I thought it would be redundant

No it is not! Now go and read the sticky post at the start and modify your code to include that tags and we will be in business.

Thinking back to when I was learning programming I can see that writing the code as a "top down" flow is silly.

Routines become cluttered and it is hard to understand what is going on - or can become.

Having routines breaks things down and you can see things happening at "block" layers instead of individual instructions.

Fair enough.

But when it is suggested that I use pins 12, 13, 14 (for example) to do other things, WHERE do I find their initial definitions to negate them?

Yes, the libraries may define pins for use as well - which aren't included in this post - and as much as I can sort of see why they can - it confuses me no end.

I guess what is also hindering me is that although I have printed the file - sometimes it is nice to have the paper in your hands rather than on a screen - some lines wrap and because I am not familiar with the syntax of the code, I get confused there as well.

Yes, that's my problem and I accept that. Where I need help is understanding the blocks/routines and how they are layed out and where the data is given to them and where/how they return values.

I've corrected your first code posting, now it's your turn to do the same for your second.

Good job you noticed you ddn't understand code before yours grew too big.

Grumpy,

It isn't the code, but more the structure I am asking about.

AWOL, I shall try to edit it, but am still looking for the EDIT button.

I have many times clicked on the NOTIFY button, mis-reading it as MODIFY.

(Blush)

Found it.

All these different forums have different layouts which makes it difficult to find your way.

But when it is suggested that I use pins 12, 13, 14 (for example) to do other things, WHERE do I find their initial definitions to negate them?

Not sure what you mean by negate them. The can be defined as numbers in the commands that use them, like digitalWrite(13, HIGH) or as variables or constants who's value is defined elsewhere like digitalWrite(13, HIGH), Do a search in the code for something like int pin 13 or what ever value it is.

Grumpy,

Say these pins are used for something in the code, and they can be used for something else.

Ok, the code as is has a buzzer output which I shall change to a toggle output which comes on for ‘x’ minutes every time an alarm is triggered.

I am wanting to include an MP3 shield to play back a sound.

I also want the GPS module.

Liudr tells me there aren’t enough pins.

I can believe that, as there are only a finite number of them.

So he said I could use (EXAMPLE!) pins 12, 13, 14 to do what ever.

Ofcourse they are already used by the code (somewhere) but I can change the code to use them for my needs.

Granted I can write my code/routine and use those pins, but it will be annoying/difficult if I don’t remove/negate their definitions in the original code.

Sure I can do a “search” for them, but I am asking for help understanding finding their definitions in the code using my eyes rather than “searching” for them.

I am seeing lines like:

# define btn_u 5

which I am guessing defines the name “btn_u” to pin 5, but I am only GUESSING.

Sure no harm if I am wrong, but it just makes the learning curve that much more … annoying/difficult.

I really hope I can get my head around this as it isn’t rocket science. Maybe just a slight push in the right direction will be all I need.

but it will be annoying/difficult if I don't remove/negate their definitions in the original code.

No you don't need to negate anything. Normally in a sketch you only use one pin for one purposes because it is attached to hardware you are truing to control.

So he said I could use (EXAMPLE!) pins 12, 13, 14 to do what ever.

Yes but they have to be attached to something. It is not the definition of the pin you want to remove, it is the code that does stuff to the pin because it will be doing the wrong stuff if you don't attache the right hardware.

Suppose pin 12 is connected to an LED and you want to blink it then you will toggle it at set intervals, that is you will first set it high and then low at set intervals. Now suppose you want to use that pin to control a motor and for that motor to be on until it hits a switch. Then you have to remove the toggling code and replace it with the code that does the new stuff. The point is you might as well just write a new sketch.

Sure I can do a "search" for them, but I am asking for help understanding finding their definitions in the code using my eyes rather than "searching" for them.

The problem with using your eyes is that if the code is any length you will miss some instances, a search makes sure you spot them all, then you use your eyes to read that line and see if it is relevant.

So look for lines that have pinMode(), digitalWrite(), digitalRead(), analogRead(), and analogWrite(), they do stuff to the pins.

So this code defines some pins:-

#define btn_u 5
#define btn_d 10
#define btn_l 11
#define btn_r 4
#define btn_b 14
#define btn_a 15


They are use here to put into an array:-

byte pins[]={btn_u,btn_d,btn_l,btn_r,btn_b,btn_a}; // The digital pins connected to the 6 buttons.


This in turn is used in calling a function:-

phi_button_groups my_btns(mapping, pins, total_buttons);
.
.
.
multiple_button_input * keypads[]={&my_btns,&debug_keypad,0};


The problem I think you face is that that code makes extensive use of library defined functions and you never see those pins being used. Search the library files to see them actually do stuff.