19
Arch1 LCD Lab Eric Freudenthal

Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

Embed Size (px)

Citation preview

Page 1: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

Arch1 LCD LabEric Freudenthal

Page 2: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

Topics

• Score Demo• LCD

• Panel Geometry• Utilities to draw to the display

• Drawing characters• Buttons

• Nuisance: multiple versions• Interrupt handlers

• Timer interrupt handler • To update score

• Ball Demo• Drawing Ball• Motion

• Paddle Demo• Buttons• Drawing paddle

Page 3: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

Panel geometry

• Panel dimensions (lcd_backend.h)• Rows:

• Top: 0• Bottom: 68 (MAX_X)• Broken into 8 row “chunks”

• major = row/8, minor=row%8

• Columns• Left: 0• Right: 96 (MAX_X)

Bit 0

Bit 7

Bit 0

Bit 7

Bit 0

Bit 7

Bit 0

Bit 7

Bit 0

Bit 7

Bit 0

Bit 7

0 0 0 1 0 1 2 0 2 3 0 3 4 0 4 5 0 5 6 0 6 7 0 7 8 1 0 9 1 110 1 211 1 312 1 413 1 514 1 615 1 7

Row #

Major(row / 8)

Minor(row % 8)

0 1 2 3 4 5

0x00 0x20 0x10 0x08 0x04 0x02

Bit 0

Bit 7

Bit 0

Bit 7

Bit 0

Bit 7

Bit 0

Bit 7

Bit 0

Bit 7

Bit 0

Bit 7

Page 4: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

lcd_char.cconst char font5x7[][5] = { // basic 5x7 font indexed as [char][chunk#] {0x00, 0x00, 0x00, 0x00, 0x00} // 20 (space) ,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 ! ,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 " ,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 # ,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $ ,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 % ,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 & ,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 ' ,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 ( ,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 ) ,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a * ,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b + ,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c , ,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d - ,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e . ,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f / ,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0 ,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1 ,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2

Page 5: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

lcd_utils.h#ifndef lcd_utils_included#define lcd_utils_included

#include "booster1202.h"#include "lcd_backend.h"

/* compute major & minor row numbers */u_char lcd_getYMajor(u_char y);u_char lcd_getYMinor(u_char y);

/* displays a chunk (byte of binary pixels) at the given address */void lcd_setAddr(u_char x, u_char yMajor); /* set addr of next write */void lcd_writeChunk(char chunk); /* write chunk and increment x */

/* set addr & write */void lcd_writeChunkAddr(char chunk, u_char xPos, u_char yMajor);

/* converts ints to character sequences */char* itoa(int value, char* result, int base);

#endif // lcd_utils_included

Page 6: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

lcd_char.c

void _lcd_writeChar(char c); /* forward declaration */

void lcd_writeString(const char *string, u_char x, u_char yMajor){ lcd_setAddr(x,yMajor); while (*string) { _lcd_writeChar(*string++); lcd_writeChunk(0); /* whitespace after char */ }}

// helper: writes 1 char at current column, advances columnvoid _lcd_writeChar(char c){ char i; for (i = 0; i < 5; i++) { lcd_writeChunk(font5x7[c - 0x20][i]); }}

void lcd_writeChar(char c, u_char x, u_char yMajor){ lcd_setAddr(x,yMajor); _lcd_writeChar(c);}

Page 7: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

paddle_buttons.h

/* P2 bits for paddle buttons */

# define LeftSw BIT2# define DownSw BIT3# define UpSw BIT4

#if LCD1202_VERSION == 3# define RightSw BIT1#elif LCD1202_VERSION == 1 || LCD1202_VERSION == 2 || LCD1202_VERSION == 4# define RightSw BIT5#else# error +++++# error +++++ LCD1202_VERSION not (properly) defined. See note in Makefile.# error +++++#endif

Page 8: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

score_demomain()

void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer lcdinit(); // init LCD (also: CPU clock to 16MHz)

CCTL0 = CCIE; // CCR0 interrupt enabled TACTL = TASSEL_2 + MC_1 + ID_3; // Set timer clock to CPU clock/8 CCR0 = 50000; // Interrupt every 10 ms

initializeSwitchInterrupts(); resetPaddle();

or_sr(0x18); // CPU off, GIE on}

Page 9: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

score_demo.cscores & timer interrupt

void updateScore(void) { char numString[] = " "; score++; lcd_writeString(" ",72,0); itoa(score, numString, 10); lcd_writeString(numString,72,0);}

void resetScore(void){ score = 0;}

/* timer interrupt */interrupt(TIMER0_A0_VECTOR) Timer_0(void){ static int clockDivide = 0; if (clockDivide++ > 20) { updateScore(); clockDivide = 0; }}

Timer_0:push r15push r14push r13push r12mov &clockDivide, r15mov r15, r14add #1, r14mov r14, &clockDividecmp #21, r15jl .L9call #updateScoremov #0, &clockDivide

.L9: pop r12pop r13pop r14pop r15reti

Page 10: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

paddle_buttons.h

/* P2 bits for paddle buttons */

# define LeftSw BIT2# define DownSw BIT3# define UpSw BIT4

#if LCD1202_VERSION == 3# define RightSw BIT1#elif LCD1202_VERSION == 1 || LCD1202_VERSION == 2 || LCD1202_VERSION == 4# define RightSw BIT5#else# error +++++# error +++++ LCD120_VERSION not (properly) defined. See note in Makefile.# error +++++#endif

Page 11: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

score_demo.csetupswitchinterrupts

unsigned char oldP1SwVal, oldP2SwVal;

#define P1SwMask SW1 //P1.3#define P2SwMask (UpSw + DownSw + LeftSw + RightSw)

void initializeSwitchInterrupts() /* setup interrupts on switch */{ P1REN |= P1SwMask; /* resistors for switches */ P2REN |= P2SwMask; P1OUT |= P1SwMask; /* pull-ups for switches */ P2OUT |= P2SwMask; oldP1SwVal = P1IN & P1SwMask; /* remember current switch vales */ oldP2SwVal = P2IN & P2SwMask; P1IES = oldP1SwVal; /* interrupt when switch bits change */ P2IES = oldP2SwVal; P1IE = P1SwMask; /* enable interrupts from switches */ P2IE = P2SwMask;}

Page 12: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

score_demo.cSW1 interrupt handlers

/* Switches on P1 (far right switch) */interrupt(PORT1_VECTOR) Port_1(void){ unsigned char p1Val = P1IN & P1SwMask; /* read switches from p1 */ P1IES= p1Val; /* interrupt on value change */ P1IFG = 0; /* clear pending P1 interrupts */ if (!(p1Val & SW1) && (oldP1SwVal & SW1)) /* unpressed to pressed? */ resetScore(); /* re-initialize score */ oldP1SwVal = p1Val;}

Output from gcc –S –O1

__isr_2:push r15push r14push r13push r12push r11mov.b &__P1IN, r11and.b #8, r11mov.b r11, &__P1IESmov.b #0, &__P1IFGjne .L6mov.b &oldP1SwVal, r15and #8, r15jeq .L6call #resetScore

.L6: mov.b r11, &oldP1SwValpop r11pop r12pop r13pop r14pop r15reti

.

Page 13: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

Topics

• Score Demo• LCD

• Panel Geometry• Utilities to draw to the display

• Drawing characters• Buttons

• Nuisance: multiple versions• Interrupt handlers

• Timer interrupt handler • To update score

• Ball Demo• Drawing Ball• Motion

• Paddle Demo• Buttons• Drawing paddle

Page 14: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

Ball_demo.cdrawing 2x2 ball

void drawBall(u_char x, u_char y){ u_char majorYTop = lcd_getYMajor(y); u_char majorYBot = lcd_getYMajor(y+1); u_char minorYTop = lcd_getYMinor(y); u_char minorYBot = lcd_getYMinor(y+1); clearBall(last_ball_x, last_ball_y); if (majorYTop == majorYBot) { // set the appropriate bits within the upper byte u_char chunk = (3 << minorYTop); lcd_writeChunkAddr(chunk, x, majorYTop); lcd_writeChunk(chunk); } else { // set the appropriate bit for the upper byte u_char chunk = (1 << minorYTop); lcd_writeChunkAddr(chunk, x, majorYTop); lcd_writeChunk(chunk); // set the appropriate bit for the lower byte chunk = (1 << minorYBot); lcd_writeChunkAddr(chunk, x, majorYBot); lcd_writeChunk(chunk);

} last_ball_x = x; last_ball_y = y;}

static void clearBall(u_char x, u_char y){ u_char yMajor = lcd_getYMajor(y); lcd_writeChunkAddr(0, x, yMajor); lcd_writeChunk(0); // x+1 lcd_writeChunkAddr(0, x, yMajor + 1); lcd_writeChunk(0); // x+1}

Page 15: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

Ball_demo.ctimer & buttoninterrupt handlers

/* timer interrupt */interrupt(TIMER0_A0_VECTOR) Timer_0(void){ static int clockDivide = 0; if (clockDivide++ > 20) { updateBall(); clockDivide = 0; }}

interrupt(PORT1_VECTOR) Port_1(void){ unsigned char p1Val = P1IN & P1SwMask; /* read switches from p1 */ P1IES= p1Val; /* interrupt on value change */ P1IFG = 0; /* clear pending P1 interrupts */ if (!(p1Val & SW1) && (oldP1SwVal & SW1)) /* transition from unpressed to pressed? */ resetBall(); /* re-initialize paddle */ oldP1SwVal = p1Val;}

Page 16: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

Ball_demo.cball motion

updateBall(){ /* reverse ball direction at court boundaries */ if ((ballXPos == 0) || (ballXPos == MAX_X -2)) ballXVel = -ballXVel; if ((ballYPos == 0) || (ballYPos == MAX_Y -2)) ballYVel = -ballYVel;

/* move ball */ ballXPos += ballXVel; ballYPos += ballYVel;

/* draw ball */ drawBall(ballXPos, ballYPos);}

Page 17: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

Topics

• Score Demo• LCD

• Panel Geometry• Utilities to draw to the display

• Drawing characters• Buttons

• Nuisance: multiple versions• Interrupt handlers

• Timer interrupt handler • To update score

• Ball Demo• Drawing Ball• Motion

• Paddle Demo• Drawing paddle• Buttons• Motion

Page 18: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

draw_paddle.c

void drawPaddle(u_char yPos) /* ypos is middle of paddle */{ char paddleTopYMajor = lcd_getYMajor(yPos-paddleSize); char paddleBotYMajor = lcd_getYMajor(yPos+paddleSize); u_char yMajor; /* yMajor row index */ u_char yMajorLimit = max(paddleBotYMajor, oldPaddleBotYMajor); for (yMajor = min(paddleTopYMajor, oldPaddleTopYMajor); yMajor <= yMajorLimit; yMajor++) { // yMajor in paddle lcd_setAddr(0, yMajor); if (yMajor < paddleTopYMajor || yMajor > paddleBotYMajor) lcd_writeChunk(0); /* erase if above or below paddle */ else { u_char chunk = 0xffu; /* default: all pixels on */ if (yMajor == paddleTopYMajor) { /* top chunk, clear top pixels */

chunk &= ~chunkMasks[lcd_getYMinor(yPos-paddleSize)]; } if (yMajor == paddleBotYMajor) { /* bot chunk, clear bottom pixels */

chunk &= chunkMasks[1+lcd_getYMinor(yPos+paddleSize)]; } lcd_writeChunk(chunk); } } oldPaddleBotYMajor = paddleBotYMajor; /* remember state */ oldPaddleTopYMajor = paddleTopYMajor;}

static const u_char chunkMasks[] = {0x00, 0x01, 0x03, 0x07, 0xf, 0x1f, 0x3f, 0x7f, 0xff};

Page 19: Arch1 LCD Lab Eric Freudenthal. Topics Score Demo LCD Panel Geometry Utilities to draw to the display Drawing characters Buttons Nuisance: multiple versions

paddle_demobuttonsmotion

/* Switches on P2 (direction pad) */interrupt(PORT2_VECTOR) Port_2(void){ unsigned char p2Val = P2IN & P2SwMask; /* read switches from p2 */ P2IES= p2Val; /* interrupt on value change */ P2IFG = 0; /* clear pending P2 interrupts */ /* just remember button state */ oldP2SwVal = p2Val;}

void updatePaddle(void) /* called by timer interrupt handler */{ // check if up switch is pressed if (!(oldP2SwVal & UpSw)) { if (paddleY > 6) paddleY--; drawPaddle(paddleY); } // check if down switch is pressed if (!(oldP2SwVal & DownSw)) { paddleY++; drawPaddle(paddleY); }}