Project

General

Profile

Download (5.11 KB) Statistics
| Branch: | Tag: | Revision:
1 633c646a henryk
/***************************************************************
2
 *
3
 * OpenBeacon.org - LED support
4
 *
5
 * Copyright 2007 Milosch Meriac <meriac@openbeacon.de>
6 5b3bd67f henryk
 * Copyright 2008 Henryk Plötz <henryk@ploetzli.ch>
7 633c646a henryk
 *
8
 ***************************************************************
9
10
    This program is free software; you can redistribute it and/or modify
11
    it under the terms of the GNU General Public License as published by
12
    the Free Software Foundation; version 2.
13
14
    This program is distributed in the hope that it will be useful,
15
    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
    GNU General Public License for more details.
18
19
    You should have received a copy of the GNU General Public License along
20
    with this program; if not, write to the Free Software Foundation, Inc.,
21
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23
*/
24
#include <FreeRTOS.h>
25
#include <AT91SAM7.h>
26
#include <lib_AT91SAM7.h>
27
#include <string.h>
28
#include <board.h>
29
#include <task.h>
30
#include "led.h"
31 5b3bd67f henryk
32
#include "gammatable.inc"
33
34 633c646a henryk
/**********************************************************************/
35
36 ba63352b henryk
#define BLINK_TIME 5
37 5b3bd67f henryk
#define PWM_PERIOD GAMMA_MAX
38
const struct channel_definition {
39
	int channel_no;
40
	enum { PERIPH_NONE=0, PERIPH_A, PERIPH_B} periph;
41
	AT91PS_PWMC_CH channel;
42
} 
43
pwm_channels[] = {
44
		[0] =  {0, PERIPH_A,  AT91C_BASE_PWMC_CH0},
45
		[1] =  {1, PERIPH_A,  AT91C_BASE_PWMC_CH1},
46
		[2] =  {2, PERIPH_A,  AT91C_BASE_PWMC_CH2},
47
		[7] =  {3, PERIPH_B,  AT91C_BASE_PWMC_CH3},
48
		[11] = {0, PERIPH_B,  AT91C_BASE_PWMC_CH0},
49
		[12] = {1, PERIPH_B,  AT91C_BASE_PWMC_CH1},
50
		[13] = {2, PERIPH_B,  AT91C_BASE_PWMC_CH2},
51
		[14] = {3, PERIPH_B,  AT91C_BASE_PWMC_CH3},
52
		[23] = {0, PERIPH_B,  AT91C_BASE_PWMC_CH0},
53
		[24] = {1, PERIPH_B,  AT91C_BASE_PWMC_CH1},
54
		[25] = {2, PERIPH_B,  AT91C_BASE_PWMC_CH2},
55
};
56 3973ad39 henryk
57 5b3bd67f henryk
static const struct channel_definition* find_channel(unsigned int led)
58
{
59
	unsigned int pos = ffs(led);
60
	if(pos==0) return 0;
61
	
62
	if(pos-1 >= sizeof(pwm_channels) / sizeof(pwm_channels[0]) ) return 0;
63
	if(pwm_channels[pos-1].periph == PERIPH_NONE) return 0;
64
	return &pwm_channels[pos-1];
65
}
66
67
// Brightness is in per thousand
68
void vLedSetBrightness(unsigned int led, int brightness)
69
{
70
	const struct channel_definition *c = find_channel(led);
71
	if(c==0) return;
72
	
73
	if(brightness < 0) brightness = 0;
74
	if(brightness > GAMMA_LEN-1) brightness = GAMMA_LEN-1;
75
	
76
	int duty = gammatable[brightness];
77
	if(duty > 1) {
78
		c->channel->PWMC_CUPDR = duty;
79
		if(c->periph == PERIPH_A) {
80
			AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, led, 0);
81
		} else if(c->periph == PERIPH_B) {
82
			AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, led);
83
		}
84
	} else {
85
	    vLedSet(led, 0);
86
	}
87
}
88
89
void vLedSet(int led, bool_t on)
90 633c646a henryk
{
91
    if(on)
92 5b3bd67f henryk
    	AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, led );
93 633c646a henryk
    else
94 5b3bd67f henryk
        AT91F_PIO_SetOutput( AT91C_BASE_PIOA, led );
95
    AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, led );
96
}
97
98
void vLedBlink(int led)
99
{
100
	volatile int i=0;
101
	vLedSet(led, 1);
102
	for(i=0; i<BLINK_TIME; i++) {vLedSet(led,0);vLedSet(led,1);}
103
	vLedSet(led, 0);	
104 633c646a henryk
}
105 5b3bd67f henryk
106 633c646a henryk
/**********************************************************************/
107 5b3bd67f henryk
void vLedSetRed(bool_t on)
108
{
109
	vLedSet(LED_RED, on);
110
}
111 633c646a henryk
112 3973ad39 henryk
void vLedBlinkRed(void)
113
{
114 5b3bd67f henryk
	vLedBlink(LED_RED);
115 3973ad39 henryk
}
116
/**********************************************************************/
117
118
void vLedSetGreen(bool_t on)
119 633c646a henryk
{
120 5b3bd67f henryk
	vLedSet(LED_GREEN, on);
121 633c646a henryk
}
122
/**********************************************************************/
123
124 3973ad39 henryk
void vLedBlinkGreen(void)
125
{
126 5b3bd67f henryk
	vLedBlink(LED_GREEN);
127 3973ad39 henryk
}
128
/**********************************************************************/
129
130 633c646a henryk
void vLedHaltBlinking(int reason)
131
{
132
    volatile u_int32_t i=0;
133
    while(1)
134
    {
135 5b3bd67f henryk
        AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED_RED | LED_GREEN );
136 633c646a henryk
        for(i=0; i<MCK/40; i++) ;
137
	
138
	switch(reason) {
139
		case 1:
140
			vLedSetGreen(1);
141
			vLedSetRed(0);
142
			break;
143
		case 2:
144
			vLedSetGreen(0);
145
			vLedSetRed(1);
146
			break;
147
		case 3:
148
			vLedSetGreen(1);
149
			vLedSetRed(1);
150
			break;
151
		case 0:
152
		default:
153
			vLedSetGreen(0);
154
			vLedSetRed(0);
155
			break;
156
	}
157
        for(i=0; i<MCK/20; i++) ;
158
	
159 5b3bd67f henryk
        AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_RED | LED_GREEN );
160 633c646a henryk
        for(i=0; i<MCK/40; i++) ;
161
    }
162
}
163
/**********************************************************************/
164
165 5b3bd67f henryk
static void init_led_pwm(unsigned int led)
166
{
167
	const struct channel_definition *c = find_channel(led);
168
	
169
	if(c==0) return;
170
	
171
	// Set PIO mapping
172
	if(c->periph == PERIPH_A) {
173
		AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, led, 0);
174
	} else if(c->periph == PERIPH_B) {
175
		AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, led);
176
	} else
177
		return;
178
	
179
	// Configure channel: clock = MCK, period = PWM_PERIOD, CPOL=1, duty cycle variable
180
	c->channel->PWMC_CMR = 0x0 | AT91C_PWMC_CPOL;
181
	c->channel->PWMC_CDTYR = 1;
182
	c->channel->PWMC_CPRDR = PWM_PERIOD;
183
	
184
	AT91C_BASE_PWMC->PWMC_ENA = (1<<(c->channel_no));
185
	vLedSetBrightness(led, 0);
186
}
187
188 633c646a henryk
void vLedInit(void)
189
{
190
    // turn off LED's 
191 5b3bd67f henryk
    AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, LED_RED | LED_GREEN );
192
    AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_RED | LED_GREEN );
193
	
194
    AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC,
195
				    ((unsigned int) 1 << AT91C_ID_PWMC));
196
    
197
    init_led_pwm(LED_GREEN);
198
    init_led_pwm(LED_RED);
199 633c646a henryk
}
Add picture from clipboard (Maximum size: 48.8 MB)