aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
blob: cfca27858ae8bb8c40f5cc9da7eda48c842f1971 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
 * This file is subject to the terms of the GFX License, v1.0. If a copy of
 * the license was not distributed with this file, you can obtain one at:
 *
 *              http://chibios-gfx.com/license.html
 */

/**
 * @file    drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
 * @brief   GDISP Graphic Driver subsystem board interface for the Olimex SAM7-EX256 board.
 *
 * @addtogroup GDISP
 * @{
 */

#ifndef _GDISP_LLD_BOARD_H
#define _GDISP_LLD_BOARD_H

// ******************************************************
// Pointers to AT91SAM7X256 peripheral data structures
// ******************************************************
static volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
static volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
static volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
static volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;

/* The PWM backlight control is non-linear on this board.
 * We pick values here that make it look a bit more linear.
 */
#define PWM_TOP_VALUE		500
#define PWM_BOTTOM_VALUE	200

#define PWM_VALUE(x)	(PWM_BOTTOM_VALUE+(PWM_TOP_VALUE-PWM_BOTTOM_VALUE)*(x)/100)

/* PWM configuration structure. The LCD Backlight is on PWM1/PB20 ie PWM2/PIN1 in ChibiOS speak */
static const PWMConfig pwmcfg = {
  1000000,		/* 1 MHz PWM clock frequency. Ignored as we are using PWM_MCK_DIV_n */
  1000,			/* PWM period is 1000 cycles. */
  NULL,
  {
   {PWM_MCK_DIV_1 | PWM_OUTPUT_ACTIVE_HIGH | PWM_OUTPUT_PIN1 | PWM_DISABLEPULLUP_PIN1, NULL},
  },
};

static bool_t pwmRunning = FALSE;

/**
 * @brief   Initialise the board for the display.
 * @notes	Performs the following functions:
 *			1. initialise the spi port used by your display
 *			2. initialise the reset pin (initial state not-in-reset)
 *			3. initialise the chip select pin (initial state not-active)
 *			4. initialise the backlight pin (initial state back-light off)
 *
 * @notapi
 */
static inline void init_board(void) {
	// *********************************************************************************************
	// InitSpi( )
	//
	// Sets up SPI channel 0 for communications to Nokia 6610 LCD Display
	//
	// I/O ports used:	PA2  = LCD Reset (set to low to reset)
	//					PA12 = LCD chip select (set to low to select the LCD chip)
	//					PA16 = SPI0_MISO Master In - Slave Out (not used in LCD interface)
	//					PA17 = SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
	//					PA18 = SPI0_SPCK Serial Clock (to LCD slave)
	//					PB20 = backlight control (normally PWM control, 1 = full on)
	//
	// *********************************************************************************************}

	/* This code should really use the ChibiOS driver for these functions */

	// Pin for backlight
	pPIOB->PIO_CODR   = PIOB_LCD_BL_MASK;    // Set PB20 to LOW
	pPIOB->PIO_OER    = PIOB_LCD_BL_MASK;    // Configure PB20 as output

	// Reset pin
	pPIOA->PIO_SODR   = PIOA_LCD_RESET_MASK;     // Set PA2 to HIGH
	pPIOA->PIO_OER    = PIOA_LCD_RESET_MASK;     // Configure PA2 as output

	// CS pin - this seems to be ignored
	// pPIOA->PIO_SODR   = 1<<12;     // Set PA2 to HIGH
	// pPIOA->PIO_OER    = 1<<12;     // Configure PA2 as output

	// Init SPI0
	// Disable the following pins from PIO control (will be used instead by the SPI0 peripheral)
	// BIT12 = PA12 -> SPI0_NPCS0 chip select
	// BIT16 = PA16 -> SPI0_MISO Master In - Slave Out (not used in LCD interface)
	// BIT17 = PA17 -> SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
	// BIT18 = PA18 -> SPI0_SPCK Serial Clock (to LCD slave)
	pPIOA->PIO_PDR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
	pPIOA->PIO_ASR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
	pPIOA->PIO_BSR = 0;

	//enable the clock of SPI
	pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;

	// Fixed mode
	pSPI->SPI_CR      = 0x81;               //SPI Enable, Sowtware reset
	pSPI->SPI_CR      = 0x01;               //SPI Enable

	//pSPI->SPI_MR      = 0xE0019;            //Master mode, fixed select, disable decoder, FDIV=1 (MCK), PCS=1110
	pSPI->SPI_MR      = 0xE0011;          //Master mode, fixed select, disable decoder, FDIV=0 (MCK), PCS=1110

	//pSPI->SPI_CSR[0]  = 0x01010C11;           //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/32*12 = 125kHz
	pSPI->SPI_CSR[0]  = 0x01010311;        //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/8 = 6MHz if using commented MR line above

	/* Display backlight control at 100% */
	pwmRunning = FALSE;
	palSetPad(IOPORT2, PIOB_LCD_BL);
}

/**
 * @brief   Set or clear the lcd reset pin.
 *
 * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
 * 
 * @notapi
 */
static inline void setpin_reset(bool_t state) {
	if (state)
		palClearPad(IOPORT1, PIOA_LCD_RESET);
	else
		palSetPad(IOPORT1, PIOA_LCD_RESET);
}

/**
 * @brief   Set the lcd back-light level.
 * @note	For now 0% turns the backlight off, anything else the backlight is on.
 *			While the hardware supports PWM backlight control, we are not using it
 *			yet.
 *
 * @param[in] percent		0 to 100%
 * 
 * @notapi
 */
static inline void set_backlight(uint8_t percent) {
	if (percent == 100) {
		/* Turn the pin on - No PWM */
		if (pwmRunning) {
			pwmStop(&PWMD2);
			pwmRunning = FALSE;
		}
		palSetPad(IOPORT2, PIOB_LCD_BL);
	} else if (percent == 0) {
		/* Turn the pin off - No PWM */
		if (pwmRunning) {
			pwmStop(&PWMD2);
			pwmRunning = FALSE;
		}
		palClearPad(IOPORT2, PIOB_LCD_BL);
	} else {
		/* Use the PWM */
		if (!pwmRunning) {
			pwmStart(&PWMD2, &pwmcfg);
			pwmRunning = TRUE;
		}
		pwmEnableChannel(&PWMD2, 0, PWM_VALUE(percent));
	}
}

/**
 * @brief   Take exclusive control of the bus
 *
 * @notapi
 */
static inline void acquire_bus(void) {
	/* Nothing to do for this board as the LCD is the only device on the SPI port */
}

/**
 * @brief   Release exclusive control of the bus
 *
 * @notapi
 */
static inline void release_bus(void) {
	// Nothing to do for this board as the LCD is the only device on the SPI port
}

/**
 * @brief   Send an 8 bit command to the lcd.
 *
 * @param[in] cmd		The command to send
 *
 * @notapi
 */
static inline void write_cmd(uint16_t cmd) {
	// wait for the previous transfer to complete
	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
	// send the command
	pSPI->SPI_TDR = cmd & 0xFF;
}

/**
 * @brief   Send an 8 bit data to the lcd.
 *
 * @param[in] data		The data to send
 * 
 * @notapi
 */
static inline void write_data(uint16_t data) {
	// wait for the previous transfer to complete
	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
	// send the data
	pSPI->SPI_TDR = data | 0x0100;
}

#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
/**
 * @brief   Read data from the lcd.
 *
 * @return	The data from the lcd
 * 
 * @notapi
 */
static inline uint16_t read_data(void) {
	#error "gdispNokia6610GE8: GDISP_HARDWARE_READPIXEL and GDISP_HARDWARE_SCROLL are not supported on this board"
	return 0;
}
#endif

#endif /* _GDISP_LLD_BOARD_H */
/** @} */