Up/Down Counter Using Logic Gates
December 5th, 2008I am a member of this Philippine Electronics Design & Electronics Repair Forum and queries from students for schematics sometimes comes up. A poster asked for a schematic diagram for an UP/Down counter using logic gates on this thread. Here’s my take:

Download the simulation file here Up/Down Counter Simulation File.
SMS Sender
November 19th, 2008GSM SMS Controller Using Bluetooth Cellular Phone and BTSerial1
November 14th, 2008The project is a GSM SMS Controller without using any GSM modem. This is using the BTSerial 1 module which wirelessly connects to a Bluetooth cellular phone to the PIC16LF876A’s serial port.
It accepts commands from an SMS incoming message and also respond via SMS on a read command request.
Read more here.
Click and view the source documentations.
GSM SMS Controller Using Bluetooth Cellular Phone and BTSerial1
November 14th, 2008The project is a GSM SMS Controller without using any GSM modem. This is using the BTSerial1 module which wirelessly connects to a Bluetooth cellular phone to the PIC16LF876A’s serial port.
It accepts commands from an SMS incoming message and also respond via SMS on a read command request.
The valid SMS commands that are:
| LED1 ON | - turns ON LED1 |
| LED1 OFF | - turns OFF LED1 |
| LED2 ON | - turns ON LED2 |
| LED2 OFF | - turns OFF LED2 |
| LED3 ON | - turns ON LED3 |
| LED3 OFF | - turns OFF LED3 |
| LED4 ON | - turns ON LED4 |
| LED4 OFF | - turns OFF LED4 |
| READ ADC | - will respond back to the sender the current ADC reading |
The project is using tthreads as its multitasking engine. And the SMS sending and receiving is using PDU mode for compatibility with more Bluetooth phones.
The following are excerpts from the full source code:
static void pack7(unsigned char bank2 *msg)
{
unsigned char i, h, c;
i=0;
h=0;
while(msg[i])
{
c = (msg[i+1] << (7-h)) | (msg[i] >> h);
bts1_putch(bin2bcd(c>>4));
bts1_putch(bin2bcd(c));
++h;
++i;
if (h==7)
{
h=0;
++i;
}
}
}
void bts1_interface_sms_recv(unsigned char c)
{
static unsigned char state = SMS_DECODE_START;
static unsigned char skip_chars = 0;
static unsigned char v, t, bits;
if (c==’r’ || c==’n’ || c==0)
{
if (state >= SMS_MESSAGE1)
{
sms_decoded(0);
}
state = SMS_DECODE_START;
skip_chars = 0;
return;
}
if (skip_chars)
{
–skip_chars;
return;
}
switch(state)
{
case SMS_DECODE_START:
v = bcd2bin(c);
v <<= 4;
++state;
break;
case SMS_GET_SMS_CENTER_LEN:
v += bcd2bin(c);
++state;
skip_chars = (v + 1) * 2;
break;
case SMS_GET_SENDER_LEN1:
send_buffer[0] = c;
v = bcd2bin(c);
v <<= 4;
++state;
break;
case SMS_GET_SENDER_LEN2:
send_buffer[1] = c;
v += bcd2bin(c);
if (v & 1)
++v;
v += 2;
send_buffer_len = 2;
++state;
break;
case SMS_GET_SENDER:
send_buffer[send_buffer_len] = c;
++send_buffer_len;
--v;
if (v==0)
{
send_buffer[send_buffer_len] = 0;
skip_chars = 20;
bits = 0;
v = 0;
t = 0;
++state;
}
break;
case SMS_MESSAGE1:
v = bcd2bin(c) << 4;
++state;
break;
case SMS_MESSAGE2:
v += bcd2bin(c);
t += ((v & (bit_mask[7-bits]-1)) << bits);
sms_decoded(t);
t = v >> (7-bits);
++bits;
if (bits>=7)
{
sms_decoded(t);
bits = 0;
t = 0;
}
–state;
break;
}
}
Click and view the source documentations.
Download the hex file here GSM SMS Controller Using Bluetooth Cellular Phone and BTSerial1 Hex File.
The complete project file is here GSM SMS Controller Using Bluetooth Cellular Phone and BTSerial1 Complete Project Files.
Dallas DS1620 Digital Thermometer/Thermostat Routines
October 28th, 2008Dallas DS1620 is an integrated circuit that functions as a digital thermometer or thermostat. This device uses a 3-wire interface to read and write data to it. This is added to MCUs that does not have A/D (analog to digital) converters and must rely on external components for temperature monitoring.
The functions below does the reading and writing data to the DS1620:
void DS1620_Write(unsigned char data)
{
unsigned char i;
TRIS_DQ = 0;
TRIS_CLK = 0;
TRIS_RST = 0;
CLK = 1;
for (i=0; i<8; ++i)
{
CLK = 0;
if (data & 1)
{
DQ = 1;
}
else
{
DQ = 0;
}
data = data >> 1;
CLK = 1;
}
}
unsigned char DS1620_Read(void)
{
unsigned int t;
unsigned char i;
TRIS_DQ = 1;
TRIS_CLK = 0;
TRIS_RST = 0;
CLK = 1;
t = 0;
for (i=0; i<9; ++i)
{
CLK = 0;
t = t >> 1;
if (DQ)
{
t = t | 0×100;
}
CLK = 1;
}
t = t >> 1;
return(t & 0xFF);
}
HD44780 LCD Routines in C
October 28th, 2008This is my implementation of interfacing the HD44780 Hitachi LCD and its variants. This uses 4 bit mode thus lesser wires going to the LCD. The port used on this is PORTB. The lower 4 bits RB0-RB3 are the data nybble. While RS and EN are RB4 and RB5, respectively.
These are some sample functions that are included on this release:
void lcd_clear(void)
{
set_LCD_RS(0);
lcd_write(0x01);
DelayMs(2);
}
void lcd_puts(const char *s)
{
set_LCD_RS(1);
while (*s) lcd_write(*s++);
}
void lcd_putch(uchar c)
{
set_LCD_RS(1);
lcd_write(c);
}
void lcd_goto(uchar pos)
{
set_LCD_RS(0);
lcd_write(0x80|(pos & 0x7F));
}
I2C Routines for PIC Microcontroller
October 28th, 2008This is a release of my master mode I2C routines for PIC microcontroller to the open source community. This uses bit-banging technique and does not use the hardware SSP peripheral. The routine checks for I2C slave acknowledgment during writing.
Here is an excerpt for writing a byte to to the I2C bus:
unsigned char i2c_write(unsigned char c)
{
unsigned char i;
SCL_LOW();
i=8;
SDA_TRIS=0;
do {
if (c & 0x80) {
SDA_HIGH();
} else {
SDA_LOW();
}
//pulse clock
delay_settle();
SCL_HIGH();
delay_clock();
SCL_LOW();
delay_clock();
c<<=1; //next bit
} while (--i);
//get acknowledge
SDA_HIGH();
SCL_HIGH();
delay_half_clock();
if (SDA) {
//SDA remains high, not acknowledged
delay_half_clock();
SCL_LOW();
delay_clock();
return I2C_ERROR_NO_ACK;
}
delay_half_clock();
SCL_LOW();
delay_clock();
return I2C_NO_ERROR;
}
Billiard Shot Clock/Timer
October 27th, 2008I have created open project as a billiards shot clock/timer. This is a 45 second countdown timer to limit the player’s time on each shot. This uses Tiny Threads as its multitasking engine for the display and button debouncing. More information, full schematics and source code can be found and downloaded here.
Billiard Shot Timer
October 27th, 2008I had posted this project at one Filipino Electronics forum here.
Download the compile .hex file here Billiard Shot Timer Source Code and Hex File

/*
* 2 Digit Billiard Timer
* Copyright (c) 2008, Regulus Berdin
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL REGULUS BERDIN BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* History:
* 1.0 10/27/2008 Created file.
*
*/
#include
__CONFIG(PROTECT & CPD & LVPDIS & BOREN & MCLREN & PWRTEN & WDTDIS & XT);
#include “tthread.h”
#define BTN_RESET RB0
#define BTN_START_STOP RB1
#define BTN_EXTEND RB2
#define TICKS_SECONDS 225
#define DEBOUNCE_DELAY 12
unsigned char tmr_count, start_count, seconds;
unsigned char debounce1, debounce2, debounce3;
unsigned char disp1, disp2;
void interrupt isr(void)
{
T0IF = 0;
if (start_count)
{
if (tmr_count)
{
–tmr_count;
}
else
{
tmr_count = TICKS_SECONDS;
++seconds;
}
}
if (debounce1) –debounce1;
if (debounce2) –debounce2;
if (debounce3) –debounce3;
}
void init(void)
{
/* disable comparators */
CMCON=0×07;
/* setup PIOs*/
TRISA=0;
TRISB=0b00000111;
PORTA=0;
PORTB=0;
RBPU = 0;
/* Timer0 on Fosc */
T0CS = 0;
/* Prescaler on Timer0 */
PSA = 0;
/* Divided by 16
Timer0 = 225 ticks/seconds */
PS0 = 1;
PS1 = 1;
PS2 = 0;
T0IF = 0;
T0IE = 1;
GIE = 1;
}
void update_dispay(void)
{
PORTA = disp1 & 0×0F;
PORTB = (disp2 << 4) & 0xF0;
}
void reset_display(unsigned char a, unsigned char b)
{
disp1 = a;
disp2 = b;
T0IF = 0;
TMR0 = 0;
update_dispay();
}
TT_DEF(display)
{
TT_BEGIN(display);
reset_display(4,5);
seconds = 0;
while (1)
{
TT_WAIT_UNTIL(display, seconds);
--seconds;
TT_SWITCH(display);
if (disp2)
--disp2;
else
if (disp1)
{
disp2 = 9;
--disp1;
}
else
{
start_count = 0;
}
TT_SWITCH(display);
update_dispay();
}
TT_END(display);
}
TT_DEF(reset)
{
TT_BEGIN(reset);
while(1) {
do {
TT_WAIT_WHILE(reset, BTN_RESET);
debounce1 = DEBOUNCE_DELAY;
TT_WAIT_WHILE(reset, debounce1);
} while (BTN_RESET);
start_count = 0;
reset_display(4,5);
do {
TT_WAIT_WHILE(reset, BTN_RESET == 0);
debounce1 = DEBOUNCE_DELAY;
TT_WAIT_WHILE(reset, debounce1);
} while(BTN_RESET == 0);
}
TT_END(reset);
}
TT_DEF(start_stop)
{
TT_BEGIN(start_stop);
while(1)
{
do {
TT_WAIT_WHILE(start_stop, BTN_START_STOP);
debounce1 = DEBOUNCE_DELAY;
TT_WAIT_WHILE(start_stop, debounce1);
} while (BTN_START_STOP);
start_count = start_count?0:1;
do {
TT_WAIT_WHILE(start_stop, BTN_START_STOP == 0);
debounce2 = DEBOUNCE_DELAY;
TT_WAIT_WHILE(start_stop, debounce2);
} while(BTN_START_STOP == 0);
}
TT_END(start_stop);
}
TT_DEF(extend)
{
TT_BEGIN(extend);
while(1)
{
do {
TT_WAIT_WHILE(extend, BTN_EXTEND);
debounce3 = DEBOUNCE_DELAY;
TT_WAIT_WHILE(extend, debounce3);
} while (BTN_EXTEND);
disp1 += 3;
update_dispay();
/* reset_display(3,0); */
start_count = 1;
do {
TT_WAIT_WHILE(extend, BTN_EXTEND == 0);
debounce3 = DEBOUNCE_DELAY;
TT_WAIT_WHILE(extend, debounce3);
} while(BTN_EXTEND == 0);
}
TT_END(extend);
}
void main(void)
{
init();
start_count = 0;
TT_INIT(display);
TT_INIT(reset);
TT_INIT(start_stop);
TT_INIT(extend);
while (1)
{
TT_SCHED(display);
TT_SCHED(reset);
TT_SCHED(start_stop);
TT_SCHED(extend);
}
}



