summaryrefslogtreecommitdiff
path: root/src/cc1111/ao_arch_funcs.h
blob: d849655bb13c9dd910f05e9a12026c4c58f68624 (plain) (blame)
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
/*
 * Copyright © 2012 Keith Packard <keithp@keithp.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 */

/*
 * ao_spi.c
 */

#if !HAS_SPI_0 && !HAS_SPI_1
#define HAS_SPI_0	1
#define SPI_0_ALT_2	1
#endif

#if HAS_SPI_0 && HAS_SPI_1
#define MULTI_SPI	1
#define N_SPI		2
#else
#define MULTI_SPI	0
#define N_SPI		1
#endif

extern __xdata uint8_t	ao_spi_mutex[N_SPI];

#if MULTI_SPI
#define ao_spi_get(bus)	ao_mutex_get(&ao_spi_mutex[bus])
#define ao_spi_put(bus)	ao_mutex_put(&ao_spi_mutex[bus])
#else
#define ao_spi_get(bus)	ao_mutex_get(&ao_spi_mutex[0])
#define ao_spi_put(bus)	ao_mutex_put(&ao_spi_mutex[0])
#endif

#define AO_SPI_SPEED_FAST	17
#define AO_SPI_SPEED_200kHz	13

#if MULTI_SPI
#define ao_spi_set_speed(bus,speed) (*(bus ? &U1GCR : &U0GCR) =(UxGCR_CPOL_NEGATIVE | \
								UxGCR_CPHA_FIRST_EDGE |	\
								UxGCR_ORDER_MSB | \
								((speed) << UxGCR_BAUD_E_SHIFT)))
#else
#define ao_spi_set_speed(bus,speed) (U0GCR = (UxGCR_CPOL_NEGATIVE |	\
					      UxGCR_CPHA_FIRST_EDGE |	\
					      UxGCR_ORDER_MSB |		\
					      ((speed) << UxGCR_BAUD_E_SHIFT)))
#endif

#define ao_spi_get_slave(bus) do {			\
		ao_spi_get(bus);			\
		ao_spi_set_speed(bus,AO_SPI_SPEED_FAST);	\
	} while (0)

#define ao_spi_put_slave(bus) do {		\
		ao_spi_put(bus);		\
	} while (0)

#define ao_spi_get_mask(reg,mask,bus,speed) do {	\
		ao_spi_get(bus);			\
		ao_spi_set_speed(bus,speed);		\
		(reg) &= ~(mask);			\
	} while (0)

#define ao_spi_put_mask(reg,mask,bus) do {		\
	(reg) |= (mask); \
	ao_spi_put(bus); \
	} while (0)


#define ao_spi_get_bit(reg,bit,pin,bus,speed) do {	\
		ao_spi_get(bus);			\
		ao_spi_set_speed(bus,speed);		\
		pin = 0;				\
	} while (0)

#define ao_spi_put_bit(reg,bit,pin,bus) do {	\
		pin = 1;			\
		ao_spi_put(bus);		\
	} while (0)


/*
 * The SPI mutex must be held to call either of these
 * functions -- this mutex covers the entire SPI operation,
 * from chip select low to chip select high
 */

#if MULTI_SPI
void
ao_spi_send(void __xdata *block, uint16_t len, uint8_t bus) __reentrant;

void
ao_spi_recv(void __xdata *block, uint16_t len, uint8_t bus) __reentrant;
#else
void
ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant;

void
ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant;

#define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len)
#define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len)
#endif

#if AO_SPI_SLAVE
void
ao_spi_send_wait(void);

void
ao_spi_recv_wait(void);
#endif

void
ao_spi_init(void);

#define token_paster(x,y)	x ## y
#define token_paster3(x,y,z)	x ## y ## z
#define token_evaluator(x,y)	token_paster(x,y)
#define token_evaluator3(x,y,z)	token_paster3(x,y,z)

#define ao_spi_init_cs(port, mask) do {			\
		port |= mask;				\
		token_evaluator(port,DIR) |= mask;	\
		token_evaluator(port,SEL) &= ~mask;	\
	} while (0)

#define cc1111_enable_output(port,dir,sel,pin,bit,v) do {	\
		pin = v;					\
		dir |= (1 << bit);				\
		sel &= ~(1 << bit);				\
	} while (0)

#define disable_unreachable	_Pragma("disable_warning 126")

#define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v)
#define ao_gpio_set(port, bit, pin, v) ((pin) = (v))
#define ao_gpio_get(port, bit, pin) (pin)
#define ao_gpio_get_bits(port) (port)
#define ao_gpio_set_bits(port, bits) ((port) |= bits)
#define ao_gpio_clr_bits(port, bits) ((port) &= ~bits)