da51973669f6d5c2516b726b62ceaabfcc3b4a20
[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
21 /* private prototypes */
22 void display_send_byte(char c);
23 void display_reset();
24 void display_update();
25
26 void set_msg(char* newmsg, u8 wrap) {
27         char* dest = current_message;
28         /* equivalent of a string copy */
29         /* while (dest++ = newmsg++); */
30         msg_length = 0;
31         while (newmsg) {
32                 dest = newmsg;
33                 dest++;
34                 newmsg++;
35                 msg_length++;
36         }
37         wrap_mode = wrap;
38         scroll_point = 0;
39         display_update();
40 }
41
42 void display_shift() {
43         /* update the display for WRAP_SCROLL or WRAP_ALTERNATE modes */
44         switch (wrap_mode) {
45                 case WRAP_SCROLL:
46                         scroll_point++;
47                         if (scroll_point >= msg_length) scroll_point = 0;
48                         display_update();
49                         break;
50                 case WRAP_ALTERNATE:
51                         scroll_point += 10;
52                         if (scroll_point >= msg_length) scroll_point = 0;
53                         /* the above means that only sets of multiples of 10 characters
54                          * are shown (excess ones are not) */
55                         display_update();
56         }
57 }
58
59 void set_char(char c, u8 pos) {
60         /* sets a single character */
61         display_buffer[pos] = c;
62         display_update();
63 }
64
65 void display_send_byte(char c) {
66         bset_misc_output(A3800_DISPLAY_WRITE);  /* enable the display clock */
67
68         _io_ports[M6811_SPDR] = c;                  /* load SPI with byte */
69         while(!(_io_ports[M6811_SPDR]&M6811_SPIE)); /* wait for completion */
70         _io_ports[M6811_SPDR];                      /* SPDR read to clear SPIE flag */
71 }
72
73 #define DISPLAY_DELAY  100 /* ms to delay between ops - could be tweaked */
74 void display_reset() {
75         /* lower the reset line for a while */
76         bclr((void*)&_io_ports[M6811_PORTA], PORTA_DISP_RESET);
77         delay(DISPLAY_DELAY);
78         bset((void*)&_io_ports[M6811_PORTA], PORTA_DISP_RESET);
79
80         spi_enable();
81         delay(DISPLAY_DELAY);
82
83         display_send_byte(0xC0 | 10);    /* tell the controller there are 10 digits */
84         display_send_byte(0xE0);    /* set duty cycle to 100%                  */
85
86         spi_disable();
87 }
88
89 void display_update() {
90         u8 i;
91
92         for (i=0; i < 10; i++) {
93                 display_buffer[i] = current_message[(i+scroll_point)%msg_length];
94         }
95
96         /* hmmm, will this cause some flickering of the display? */
97         display_reset();
98         
99         for (i=0; i < 10; i++) {
100                 display_send_byte(display_buffer[i]&0x7f);
101         }
102 }
103
104 void display_init() {
105         display_reset();
106 }
107

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