Hangman game using qp a 16x2 LCD and joystick.

Dependencies:   TextLCD mbed qp

Files at this revision

API Documentation at this revision

Comitter:
tylerjw
Date:
Wed Feb 08 22:20:11 2012 +0000
Child:
1:4efaebc256d3
Commit message:
Problems with lib/qp, please help!
Player class hasn\t been developed yet.
BSP is still missing some features.

Changed in this revision

TextLCD.lib Show annotated file Show diff for this revision Revisions of this file
bsp.cpp Show annotated file Show diff for this revision Revisions of this file
bsp.h Show annotated file Show diff for this revision Revisions of this file
hangman.h Show annotated file Show diff for this revision Revisions of this file
host.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
qp.lib Show annotated file Show diff for this revision Revisions of this file
qp_config.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TextLCD.lib	Wed Feb 08 22:20:11 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/simon/code/TextLCD/#44f34c09bd37
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bsp.cpp	Wed Feb 08 22:20:11 2012 +0000
@@ -0,0 +1,137 @@
+#include "qp_port.h"
+#include "hangman.h"
+#include "bsp.h"
+#include "LPC17xx.h"
+#include "mbed.h"
+
+enum ISR_Priorities { // ISR priorities from highest urgency to lowest
+    BUTTON_PRIO,
+    SYSTICK_PRIO,
+};
+
+
+#define LED_PORT      LPC_GPIO1
+#define LED1_BIT     (1U << 18)
+#define LED2_BIT     (1U << 20)
+#define LED3_BIT     (1U << 21)
+#define LED4_BIT     (1U << 23)
+
+//............................................................................
+extern "C" void SysTick_Handler(void) {
+    QK_ISR_ENTRY();                // inform the QK kernel of entering the ISR
+
+#ifdef Q_SPY
+    uint32_t volatile dummy = SysTick->CTRL; // clear the COUNTFLAG in SysTick
+    l_tickTime += l_tickPeriod;              // account for the clock rollover
+#endif
+
+    QF::TICK(&l_SysTick_Handler);             // process all armed time events
+
+    QK_ISR_EXIT();                  // inform the QK kernel of exiting the ISR
+}
+
+//............................................................................
+void BSP_init(void) {
+    SystemInit();                            // initialize the clocking system
+
+    // set LED port to output
+    LED_PORT->FIODIR |= (LED1_BIT | LED2_BIT | LED3_BIT | LED4_BIT);
+
+    // clear the LEDs
+    LED_PORT->FIOCLR  = (LED1_BIT | LED2_BIT | LED3_BIT | LED4_BIT);
+
+    QS_OBJ_DICTIONARY(&l_SysTick_Handler);
+}
+
+//............................................................................
+void BSP_lcdScrollIn(char* line1, char* line2) {
+// scroller algorithm
+    lcd.cls();
+    char output1[17];
+    char output2[17];
+    for ( int i = 0; i < 17; i++) {
+        output1[i] = ' ';
+        output2[i] = ' ';
+    }
+    for (int i = 0; i < 17; i++) {
+        for (int col = 0; col < 17; col++) {
+
+            if (col >= i) {
+                output1[col] = ' ';
+                output2[col] = ' ';
+            } else {
+                output1[col] = (line1[col+(16-i)]);
+                output2[col] = (line2[col+(16-i)]);
+            }
+            lcd.locate(col,0);
+            lcd.putc(output1[col]);
+            lcd.locate(col,1);
+            lcd.putc(output2[col]);
+        }
+        wait(0.4);
+    }
+}
+
+//............................................................................
+void BSP_lcdUpdate(char* line1,char* line2) {
+    uint8_t length1 = strlen(line1);
+    uint8_t length2 = strlen(line2);
+    if (length1 > length2)
+        length1 = length2;
+    lcd.cls();
+    if (length1 < 17)
+        for (int col = 0; col < 17 && col < length1; col++) {
+            lcd.locate(col,0);
+            lcd.putc(*(line1+col));
+            lcd.locate(col,1);
+            lcd.putc(*(line2+col));
+        }
+    else
+        for (int col = 0; col < 17; col++) {
+            lcd.locate(col,0);
+            lcd.putc(*(line1+col));
+            lcd.locate(col,1);
+            lcd.putc(*(line2+col));
+        }
+}
+
+//............................................................................
+void QF::onStartup(void) {
+    // set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate
+    SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC);
+
+    // set priorities of all interrupts in the system...
+    NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIO);
+    //NVIC_SetPriority(EINT0_IRQn,   GPIOPORTA_PRIO);
+
+    //NVIC_EnableIRQ(EINT0_IRQn);
+}
+//............................................................................
+void QF::onCleanup(void) {
+}
+//............................................................................
+void QK::onIdle(void) {
+
+    QF_INT_LOCK(dummy);
+    LED_PORT->FIOSET = LED4_BIT;                           // turn the LED4 on
+    __NOP();                        // delay a bit to see some light intensity
+    __NOP();
+    __NOP();
+    __NOP();
+    LED_PORT->FIOCLR = LED4_BIT;                          // turn the LED4 off
+    QF_INT_UNLOCK(dummy);
+
+    __WFI();
+}
+
+//............................................................................
+void Q_onAssert(char const Q_ROM * const Q_ROM_VAR file, int line) {
+    (void)file;                                      // avoid compiler warning
+    (void)line;                                      // avoid compiler warning
+    QF_INT_LOCK(dummy);          // make sure that all interrupts are disabled
+    // light up all LEDs
+    LED_PORT->FIOSET = (LED1_BIT | LED2_BIT | LED3_BIT | LED4_BIT);
+
+    for (;;) {          // NOTE: replace the loop with reset for final version
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bsp.h	Wed Feb 08 22:20:11 2012 +0000
@@ -0,0 +1,13 @@
+#ifndef bsp_h
+#define bsp_h
+
+#include "TextLCD.h"
+
+#define BSP_TICKS_PER_SEC   100     // system clock tick rate
+
+TextLCD lcd(p10, p11, p17, p18, p19, p20); // rs, e, d4-d7
+
+void BSP_init(void);
+void BSP_lcdScrollIn(char*, char*); // display functions
+void BSP_lcdUpdate(char*,char*);
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hangman.h	Wed Feb 08 22:20:11 2012 +0000
@@ -0,0 +1,29 @@
+#ifndef hangman_h
+#define hangman_h
+
+#include "bsp.h"
+
+enum HangmanSignals {
+    START_SIG,
+    PLAY_SIG,
+    SELECT_SIG,
+    WIN_SIG,
+    LOOSE_SIG,
+    FINISHED_SIG,
+    TERMINATE_SIG,
+    MAX_PUB_SIG,
+    
+    SCROLL_SIG,
+    MAX_SIG
+};
+
+struct HostEvt : public QEvent {
+    int scroll_pos; // +1 - up, 0 - nochange, -1 - down
+};
+
+enum { MAX_LETTERS = 8 };           // max wrong letters before loosing
+
+extern QActive * const AO_Player;   // active object "opaque" pointers
+extern QActive * const AO_Host;
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host.cpp	Wed Feb 08 22:20:11 2012 +0000
@@ -0,0 +1,185 @@
+#include "qp_port.h"
+#include "hangman.h"
+#include "bsp.h"
+
+class Host : public QActive {
+private:
+    char* word;
+    uint8_t selected_word;
+    uint8_t num_letters;
+    uint8_t incorrect_letters;
+    char* used_letters;
+
+    char letter;
+    char output1[17]; // buffer for display
+    char output2[17];
+
+public:
+    Host();
+
+private:
+    static QState initial(Host *me, QEvent const *e);
+    static QState welcome(Host *me, QEvent const *e);
+    static QState playing(Host *me, QEvent const *e);
+};
+
+#define BANK_SIZE   4
+char* const word_bank[] = { "hangmann", "global", "micro", "sensor" };
+char* const win_msg = "   You Win!";
+char* const loose_msg = "   You suck!";
+char* const press_play_msg = "Push to continue";
+
+
+// Local objects -------------------------------------------------------------
+static Host l_host;                                    // local Host object
+
+// Public-scope objects ------------------------------------------------------
+QActive * const AO_Host = &l_host;                    // "opaque" AO pointer
+
+//............................................................................
+Host::Host() : QActive((QStateHandler)&Host::initial) {
+}
+
+//............................................................................
+QState Host::initial(Host *me, QEvent const *e) {
+
+    QS_OBJ_DICTIONARY(&l_host);
+    QS_FUN_DICTIONARY(&QHsm::top);
+    QS_FUN_DICTIONARY(&Host::initial);
+    QS_FUN_DICTIONARY(&Host::playing);
+
+    QS_SIG_DICTIONARY(TERMINATE_SIG, 0); // global signal
+
+    QS_SIG_DICTIONARY(START_SIG, me);     // signals for Host
+    QS_SIG_DICTIONARY(SCROLL_SIG, me);
+    QS_SIG_DICTIONARY(SELECT_SIG, me);
+
+    me->subscribe(TERMINATE_SIG);
+
+    // output welcome message
+    BSP_lcdUpdate("Push btn to play mbed hangman!","");
+    wait(2.0);  // pause for 2 seconds
+
+    return Q_TRAN(&Host::welcome);
+}
+
+//............................................................................
+QState Host::welcome(Host *me, QEvent const *e) {
+    HostEvt *pe;
+
+    switch (e->sig) {
+        case START_SIG: {
+            uint8_t idx;
+
+            // init the game
+            time_t seconds = time(NULL);
+            me->selected_word = seconds % BANK_SIZE;
+            me->word = word_bank[me->selected_word];
+            me->num_letters = strlen(me->word);
+            me->incorrect_letters = 0;
+            for (int i = 0; i < 17; i++) { // clear output
+                me->output1[i] = ' ';
+                me->output2[i] = ' ';
+            }
+
+            for (idx = 0; idx < me->num_letters; idx++) {
+                me->output1[idx] = '_';
+            }
+            for (; idx < 16; idx++) {
+                me->output1[idx] = ' ';
+            }
+            me->letter = 'a';
+            idx = 16;
+            me->output1[idx] = me->letter;
+            // clear output2
+            for (idx = 0; idx < 17; idx++)
+                me->output2[idx] = ' ';
+
+            BSP_lcdUpdate(me->output1, me->output2); // update display
+
+            // post play to player
+            pe = Q_NEW(HostEvt, PLAY_SIG);
+            pe->scroll_pos = 0; // center
+            QF::PUBLISH(pe, me);
+
+            return Q_TRAN(&Host::playing);
+        }
+        case TERMINATE_SIG: {
+            QF::stop();
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm::top);
+}
+
+//............................................................................
+QState Host::playing(Host *me, QEvent const *e) {
+
+    HostEvt *pe;
+
+    switch (e->sig) {
+        case SCROLL_SIG: {
+            if (((HostEvt const *)e)->scroll_pos < 0) { // go down
+                if (me->letter == 'a') // wrap around
+                    me->letter = 'z';
+                else
+                    me->letter--;
+            } else if (((HostEvt const *)e)->scroll_pos > 0) { // go up
+                if (me->letter == 'z') // wrap around
+                    me->letter = 'a';
+                else
+                    me->letter++;
+            }
+            me->output1[16] = me->letter;
+            BSP_lcdUpdate(me->output1,me->output2);
+
+            return Q_HANDLED();
+        }
+        case SELECT_SIG: {
+            // test for letter in word
+            char * pch;
+            pch=strchr(me->word,me->letter);
+            if (pch != NULL) { // found in word
+                do {
+                    me->word[pch-me->word] = ' ';
+                    me->output1[pch-me->word] = me->letter;
+                    pch=strchr(pch+1,me->letter);
+                } while (pch!=NULL);
+                // update screen
+                BSP_lcdUpdate(me->output1,me->output2);
+                // test for win
+                if (strpbrk(me->word,"abcdefghijklmnopqrs") == NULL) { // win!
+                    BSP_lcdScrollIn(win_msg, press_play_msg); // win msg
+                    // post play to player
+                    HostEvt *pe = Q_NEW(HostEvt, WIN_SIG);
+                    pe->scroll_pos = 0; // center
+                    QF::PUBLISH(pe, me);
+
+                    // go to welcome state
+                    return Q_TRAN(&Host::welcome);
+                }
+            } else {
+                if (++me->incorrect_letters >= MAX_LETTERS) { // loose
+                    BSP_lcdScrollIn(loose_msg, press_play_msg); // message
+                    // post play to player
+                    HostEvt *pe = Q_NEW(HostEvt, WIN_SIG);
+                    pe->scroll_pos = 0; // center
+                    QF::PUBLISH(pe, me);
+
+                    // go to welcome state
+                    return Q_TRAN(&Host::welcome);
+                } else {
+                    // post to used letters
+                    me->output2[me->incorrect_letters-1] = (char)(me->letter - 33); // make uppercase
+                    BSP_lcdUpdate(me->output1,me->output2); // update screen
+                }
+            }
+            return Q_HANDLED();
+        }
+        case TERMINATE_SIG: {
+            QF::stop();
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm::top);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Feb 08 22:20:11 2012 +0000
@@ -0,0 +1,12 @@
+#include "mbed.h"
+
+DigitalOut myled(LED1);
+
+int main() {
+    while(1) {
+        myled = 1;
+        wait(0.2);
+        myled = 0;
+        wait(0.2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Feb 08 22:20:11 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/14f4805c468c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qp.lib	Wed Feb 08 22:20:11 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/QL/code/qp/#934bb9eea80b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qp_config.h	Wed Feb 08 22:20:11 2012 +0000
@@ -0,0 +1,10 @@
+#ifndef qp_config_h
+#define qp_config_h
+
+// enable preemptive QK kernel
+#define QK_PREEMPTIVE
+
+// define maximum number of active objects
+#define QF_MAX_ACTIVE
+
+#endif
\ No newline at end of file