more changes
[uccvend-snackrom.git] / ROM2 / display.c
1 /*
2  * display.c - functions for controlling the display on the vending machine.
3  *
4  * Use set_msg(char*) to write a new message to the screen, replacing the
5  * previous one. The message can be at most 255 characters long. Use
6  * set_wrap_mode with one of the WRAP_* options in vend.h to set the scrolling
7  * behaviour. If the message is less than 10 characters, it is not scrolled.
8  * Otherwise, the message will scroll.
9  *
10  */
11
12 #include "display.h"
13 #include "vend.h"
14
15 char display_buffer[10];    /* what each byte on the display reads          */
16 char current_message[256];  /* message that is scrolled or switched between */
17 u8   msg_length;            /* length of current_message                    */
18 u8   wrap_mode;             /* whether to scroll or alternate between msgs  */
19 u8   scroll_point;          /* how far through the message we have scrolled */
20 bool have_scrolled;         /* true after one scroll (used for scroll_msg())*/
21
22 /* private prototypes */
23 void display_send_byte(char c);
24 void display_reset();
25 void display_update();
26
27 void append_msg(char* newmsg, u8 wrap) {
28         char* dest = current_message+msg_length;
29         /* equivalent of a string copy */
30         while (newmsg) {
31                 dest = newmsg;
32                 dest++;
33                 newmsg++;
34                 msg_length++;
35         }
36         wrap_mode = wrap;
37 }
38
39 void set_msg(char* newmsg, u8 wrap) {
40         msg_length = 0;
41         append_msg(newmsg, wrap);
42         scroll_point = 0;
43         display_update();
44 }
45
46 void scroll_msg(char* newmsg) {
47         /* puts a message on display and does not return until the message has
48          * scrolled across once.
49          */
50         set_msg(newmsg, WRAP_SCROLL);
51         have_scrolled = 0;
52         while (!have_scrolled);
53 }
54
55 void display_shift() {
56         /* update the display for WRAP_SCROLL or WRAP_ALTERNATE modes */
57         switch (wrap_mode) {
58                 case WRAP_SCROLL:
59                 case WRAP_ALTERNATE:
60                         scroll_point++;
61                         if (scroll_point >= msg_length) {
62                                 scroll_point = 0;
63                                 have_scrolled = 1;
64                         }
65                         display_update();
66                         break;
67         }
68 }
69
70 void set_char(char c, u8 pos) {
71         /* sets a single character */
72         display_buffer[pos] = c;
73         display_update();
74 }
75
76 void display_send_byte(char c) {
77         bset_misc_output(A3800_DISPLAY_WRITE);  /* enable the display clock */
78
79         _io_ports[M6811_SPDR] = c;                  /* load SPI with byte */
80         while(!(_io_ports[M6811_SPDR]&M6811_SPIE)); /* wait for completion */
81         _io_ports[M6811_SPDR];                      /* SPDR read to clear SPIE flag */
82 }
83
84 #define DISPLAY_DELAY  100 /* ms to delay between ops - could be tweaked */
85 void display_reset() {
86         /* lower the reset line for a while */
87         bclr((void*)&_io_ports[M6811_PORTA], PORTA_DISP_RESET);
88         delay(DISPLAY_DELAY);
89         bset((void*)&_io_ports[M6811_PORTA], PORTA_DISP_RESET);
90
91         spi_enable();
92         delay(DISPLAY_DELAY);
93
94         display_send_byte(0xC0 | 10);    /* tell the controller there are 10 digits */
95         display_send_byte(0xE0);    /* set duty cycle to 100%                  */
96
97         spi_disable();
98 }
99
100 void display_update() {
101         u8 i;
102
103         for (i=0; i < 10; i++) {
104                 display_buffer[i] = current_message[
105                         (i+(wrap_mode==WRAP_ALTERNATE?scroll_point/10:scroll_point))
106                         %msg_length];
107         }
108
109         /* hmmm, will this cause some flickering of the display? */
110         display_reset();
111         
112         for (i=0; i < 10; i++) {
113                 display_send_byte(display_buffer[i]&0x7f);
114         }
115 }
116
117 void display_init() {
118         display_reset();
119 }
120

UCC git Repository :: git.ucc.asn.au