Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2004 by Jens Arnold |
Nicolas Pennequin | 357ffb3 | 2008-05-05 10:32:46 +0000 | [diff] [blame] | 11 | * Based on the work of Alan Korr and Jörg Hohensohn |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 12 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame^] | 13 | * This program is free software; you can redistribute it and/or |
| 14 | * modify it under the terms of the GNU General Public License |
| 15 | * as published by the Free Software Foundation; either version 2 |
| 16 | * of the License, or (at your option) any later version. |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 17 | * |
| 18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 19 | * KIND, either express or implied. |
| 20 | * |
| 21 | ****************************************************************************/ |
| 22 | |
| 23 | #include "config.h" |
Linus Nielsen Feltzing | 5cf3317 | 2004-10-26 06:53:34 +0000 | [diff] [blame] | 24 | #include "cpu.h" |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 25 | |
| 26 | #define LCDR (PBDR_ADDR+1) |
| 27 | |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 28 | #define LCD_DS 1 /* PB0 = 1 --- 0001 --- LCD-DS */ |
| 29 | #define LCD_CS 2 /* PB1 = 1 --- 0010 --- /LCD-CS */ |
| 30 | #define LCD_SD 4 /* PB2 = 1 --- 0100 --- LCD-SD */ |
| 31 | #define LCD_SC 8 /* PB3 = 1 --- 1000 --- LCD-SC */ |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 32 | |
| 33 | /* |
| 34 | * About /CS,DS,SC,SD |
| 35 | * ------------------ |
| 36 | * |
| 37 | * LCD on JBP and JBR uses a SPI protocol to receive orders (SDA and SCK lines) |
| 38 | * |
| 39 | * - /CS -> Chip Selection line : |
| 40 | * 0 : LCD chipset is activated. |
| 41 | * - DS -> Data Selection line, latched at the rising edge |
| 42 | * of the 8th serial clock (*) : |
| 43 | * 0 : instruction register, |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 44 | * 1 : data register; |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 45 | * - SC -> Serial Clock line (SDA). |
| 46 | * - SD -> Serial Data line (SCK), latched at the rising edge |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 47 | * of each serial clock (*). |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 48 | * |
| 49 | * _ _ |
| 50 | * /CS \ / |
| 51 | * \______________________________________________________/ |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 52 | * _____ ____ ____ ____ ____ ____ ____ ____ ____ _____ |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 53 | * SD \/ D7 \/ D6 \/ D5 \/ D4 \/ D3 \/ D2 \/ D1 \/ D0 \/ |
| 54 | * _____/\____/\____/\____/\____/\____/\____/\____/\____/\_____ |
| 55 | * |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 56 | * _____ _ _ _ _ _ _ _ ________ |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 57 | * SC \ * \ * \ * \ * \ * \ * \ * \ * |
| 58 | * \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 59 | * _ _________________________________________________________ |
| 60 | * DS \/ |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 61 | * _/\_________________________________________________________ |
| 62 | * |
| 63 | */ |
| 64 | |
| 65 | .section .icode,"ax",@progbits |
| 66 | |
| 67 | .align 2 |
| 68 | .global _lcd_write_command |
| 69 | .type _lcd_write_command,@function |
| 70 | |
| 71 | /* Write a command byte to the lcd controller |
| 72 | * |
| 73 | * Arguments: |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 74 | * r4 - command byte (int) |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 75 | * |
| 76 | * Register usage: |
| 77 | * r0 - scratch |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 78 | * r1 - command byte (copied) |
Jens Arnold | ad70a9b | 2006-11-09 07:31:31 +0000 | [diff] [blame] | 79 | * r2 - precalculated port value (CS, DS and SC low, SD high) |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 80 | * r3 - lcd port address |
| 81 | * r5 - 1 (byte count for reuse of the loop in _lcd_write_data) |
| 82 | */ |
| 83 | |
| 84 | _lcd_write_command: |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 85 | mov.l .lcdr, r3 /* put lcd data port address in r3 */ |
| 86 | mov r4, r1 /* copy data byte to r1 */ |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 87 | mov #0, r5 /* fake end address - stop after first iteration */ |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 88 | |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 89 | /* This code will fail if an interrupt changes the contents of PBDRL. |
| 90 | * If so, we must disable the interrupt here. */ |
| 91 | |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 92 | mov.b @r3, r0 /* r0 = PBDRL */ |
| 93 | or #(LCD_SD), r0 /* r0 |= LCD_SD */ |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 94 | and #(~(LCD_CS|LCD_DS|LCD_SC)),r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */ |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 95 | |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 96 | bra .single_transfer /* jump into the transfer loop */ |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 97 | mov r0, r2 |
| 98 | |
| 99 | |
| 100 | .align 2 |
| 101 | .global _lcd_write_command_e |
| 102 | .type _lcd_write_command_e,@function |
| 103 | |
| 104 | /* Write a command byte and a data byte to the lcd controller |
| 105 | * |
| 106 | * Arguments: |
| 107 | * r4 - command byte |
| 108 | * r5 - data byte |
| 109 | * |
| 110 | * Register usage: |
| 111 | * r0 - scratch |
| 112 | * r1 - command/data byte (copied) |
| 113 | * r2 - precalculated port value (CS, DS and SC low, SD high) |
| 114 | * r3 - lcd port address |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 115 | * r5 - fake end address |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 116 | * r6 - data byte (saved) |
| 117 | * r7 - saved pr |
| 118 | */ |
| 119 | |
| 120 | _lcd_write_command_e: |
| 121 | mov.l .lcdr, r3 /* put lcd data port address in r3 */ |
| 122 | mov r4, r1 /* copy data byte to r1 */ |
| 123 | mov r5, r6 |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 124 | mov #0, r5 /* fake end address - stop after first iteration */ |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 125 | |
| 126 | /* This code will fail if an interrupt changes the contents of PBDRL. |
| 127 | * If so, we must disable the interrupt here. */ |
| 128 | |
| 129 | mov.b @r3, r0 /* r0 = PBDRL */ |
| 130 | or #(LCD_SD), r0 /* r0 |= LCD_SD */ |
| 131 | and #(~(LCD_CS|LCD_DS|LCD_SC)),r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */ |
| 132 | |
| 133 | sts pr, r7 |
| 134 | bsr .single_transfer /* jump into the transfer loop */ |
| 135 | mov r0, r2 |
| 136 | |
| 137 | lds r7, pr |
| 138 | mov r6, r1 |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 139 | or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */ |
| 140 | and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */ |
| 141 | bra .single_transfer /* jump into the transfer loop */ |
| 142 | mov r0, r2 |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 143 | |
| 144 | |
| 145 | .align 2 |
| 146 | .global _lcd_write_data |
| 147 | .type _lcd_write_data,@function |
| 148 | |
| 149 | |
| 150 | /* A high performance function to write data to the display, |
| 151 | * one or multiple bytes. |
| 152 | * |
| 153 | * Arguments: |
| 154 | * r4 - data address |
| 155 | * r5 - byte count |
| 156 | * |
| 157 | * Register usage: |
| 158 | * r0 - scratch |
| 159 | * r1 - current data byte |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 160 | * r2 - precalculated port value (CS and SC low, DS and SD high) |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 161 | * r3 - lcd port address |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 162 | * r4 - current address |
| 163 | * r5 - end address |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 164 | */ |
| 165 | |
| 166 | _lcd_write_data: |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 167 | mov.l .lcdr, r3 /* put lcd data port address in r3 */ |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 168 | add r4, r5 /* end address */ |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 169 | |
| 170 | /* This code will fail if an interrupt changes the contents of PBDRL. |
| 171 | * If so, we must disable the interrupt here. If disabling interrupts |
Nicolas Pennequin | 357ffb3 | 2008-05-05 10:32:46 +0000 | [diff] [blame] | 172 | * for a long time (~9200 clks = ~830 µs for transferring 112 bytes on |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 173 | * recorders)is undesirable, the loop has to be rewritten to |
| 174 | * disable/precalculate/transfer/enable for each iteration. However, |
| 175 | * this would significantly decrease performance. */ |
| 176 | |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 177 | mov.b @r3, r0 /* r0 = PBDRL */ |
| 178 | or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */ |
| 179 | and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */ |
| 180 | mov r0, r2 |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 181 | |
| 182 | .align 2 |
| 183 | .multi_transfer: |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 184 | mov.b @r4+, r1 /* load data byte from memory */ |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 185 | |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 186 | .single_transfer: |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 187 | shll16 r1 /* shift data to most significant byte */ |
| 188 | shll8 r1 |
| 189 | |
| 190 | shll r1 /* shift the msb into carry */ |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 191 | mov r2, r0 /* copy precalculated port value */ |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 192 | bt 1f /* data bit = 1? */ |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 193 | and #(~LCD_SD), r0 /* no: r0 &= ~LCD_SD */ |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 194 | 1: |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 195 | shll r1 /* next shift here for alignment */ |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 196 | mov.b r0, @r3 /* set data to port */ |
| 197 | or #(LCD_SC), r0 /* rise SC (independent of SD level) */ |
| 198 | mov.b r0, @r3 /* set to port */ |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 199 | |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 200 | mov r2, r0 |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 201 | bt 1f |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 202 | and #(~LCD_SD), r0 |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 203 | 1: |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 204 | mov.b r0, @r3 |
| 205 | or #(LCD_SC), r0 |
| 206 | mov.b r0, @r3 |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 207 | |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 208 | shll r1 |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 209 | mov r2, r0 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 210 | bt 1f |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 211 | and #(~LCD_SD), r0 |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 212 | 1: |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 213 | shll r1 |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 214 | mov.b r0, @r3 |
| 215 | or #(LCD_SC), r0 |
| 216 | mov.b r0, @r3 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 217 | |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 218 | mov r2, r0 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 219 | bt 1f |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 220 | and #(~LCD_SD), r0 |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 221 | 1: |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 222 | mov.b r0, @r3 |
| 223 | or #(LCD_SC), r0 |
| 224 | mov.b r0, @r3 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 225 | |
| 226 | shll r1 |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 227 | mov r2, r0 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 228 | bt 1f |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 229 | and #(~LCD_SD), r0 |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 230 | 1: |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 231 | shll r1 |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 232 | mov.b r0, @r3 |
| 233 | or #(LCD_SC), r0 |
| 234 | mov.b r0, @r3 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 235 | |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 236 | mov r2, r0 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 237 | bt 1f |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 238 | and #(~LCD_SD), r0 |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 239 | 1: |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 240 | mov.b r0, @r3 |
| 241 | or #(LCD_SC), r0 |
| 242 | mov.b r0, @r3 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 243 | |
| 244 | shll r1 |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 245 | mov r2, r0 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 246 | bt 1f |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 247 | and #(~LCD_SD), r0 |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 248 | 1: |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 249 | shll r1 |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 250 | mov.b r0, @r3 |
| 251 | or #(LCD_SC), r0 |
| 252 | mov.b r0, @r3 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 253 | |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 254 | mov r2, r0 |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 255 | bt 1f |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 256 | and #(~LCD_SD), r0 |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 257 | 1: |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 258 | mov.b r0, @r3 |
| 259 | or #(LCD_SC), r0 |
| 260 | mov.b r0, @r3 |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 261 | |
Jens Arnold | b30ca8c | 2008-01-14 18:47:00 +0000 | [diff] [blame] | 262 | cmp/hi r4, r5 /* some blocks left? */ |
| 263 | bt .multi_transfer |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 264 | |
| 265 | or #(LCD_CS|LCD_DS|LCD_SD|LCD_SC),r0 /* restore port */ |
Michael Sevakis | e89a394 | 2006-11-08 16:13:04 +0000 | [diff] [blame] | 266 | rts |
Jens Arnold | cb1c9e4 | 2007-03-18 17:58:49 +0000 | [diff] [blame] | 267 | mov.b r0, @r3 |
Jens Arnold | e48cc2a | 2004-05-10 11:38:24 +0000 | [diff] [blame] | 268 | |
| 269 | /* This is the place to reenable the interrupts, if we have disabled |
| 270 | * them. See above. */ |
| 271 | |
| 272 | .align 2 |
| 273 | .lcdr: |
| 274 | .long LCDR |