Billiard Shot Timer

I 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.

This is posted at a Filipino Electronics forum here.

This is a billiard shot clock where there is a countdown of 45 seconds. The first button will reset the clock to 45 seconds. The next button starts the countdown when pressed. Pressing again the button stops the clock. The last button is the extend button. This will reset the clock to 30 seconds and starts the count immediately.

Below is the schematic:
Billiard Shot Clock Schematic

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);
    }
}

Leave a Reply

Google