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
|
/************************************************************************/
/* */
/* File: avr/usi.c */
/* Description: serial line device. */
/* Version: 1.0 */
/* Author: Otto Mattik */
/* */
/* (C)Copyright Otto Mattik 2014-2021. */
/* */
/* This file is a part of 'armen' (a tiny operating system). */
/* 'armen' is distributed under the CeCILL-V2.1 licence. For more */
/* details about this licence, please visit the website cecill.info */
/* */
/************************************************************************/
#ifndef AVR_UART_C
#error "do not use this code directly, it must be included via avr_uart.c"
#endif
#ifdef USE_PWM
#error "pwm and uart, used together, are incompatible"
#endif
/* TO DO: implement serial line via usi interface */
#include <avr/io.h>
#include <avr/interrupt.h>
/*
* this code is based on the AVR307 publication.
* it use the timer 1 (16 bits on ATtiny84, 8 bits on ATtiny85).
* the uart is configured with 8 data bits, no parity and 1 stop bit.
* the used pins are DI (input) and DO (output).
*/
#if defined(__AVR_ATtiny84__)
#define USI_INPUT_PIN PA6 /* receive */
#define USI_OUTPUT_PIN PA5 /* transmit */
#define USI_CONFIG_PINS() (\
PORTA |= (1<<USI_INPUT_PIN),\
DDRA = (DDRA\
| (1<<USI_OUTPUT_PIN))\
& ~(1<<USI_INPUT_PIN)\
)
#define USI_INPUT_START_BIT() (PINA & (1<<USI_INPUT_PIN) ? 0 : 1)
#define USI_CONFIG_TIMER(p) (\
TIMSK1 = 0, TCCR1A = 0,\
TCCR1B = (1<<ICNC1) | (p)\
)
#define USI_CONFIG_DEVICE() ()
#define USI_INPUT_CAPTURE_INT PCINT6_vect
#elif defined(__AVR_ATtiny85__)
#define USI_INPUT_PIN PB0 /* receive */
#define USI_OUTPUT_PIN PB1 /* transmit */
#define USI_CONFIG_PINS() (\
PORTB |= (1<<USI_INPUT_PIN),\
DDRB = (DDRB\
| (1<<USI_OUTPUT_PIN))\
& ~(1<<USI_INPUT_PIN)\
)
#define USI_INPUT_START_BIT() (PINB & (1<<USI_INPUT_PIN) ? 0 : 1)
#define USI_CONFIG_TIMER(p) (TIMSK = 0, TCCR1 = (p))
#define USI_CONFIG_DEVICE() ()
#define USI_INPUT_CAPTURE_INT PCINT0_vect
#else
#error "no or unavailable cpu defined"
#endif
#define USI_OVERFLOW_INTERRUPT USI_OVF_vect
#define TIMER_OVERFLOW_INTERRUPT TIMER1_OVF_vect
#define CONFIG_RS485(p) (CONFIG_RS485_DRIVER(), \
CONFIG_TIMER_PRESCALE(p), \
CONFIG_USI_DEVICE())
#define USI_RX_BUFFER_SIZE 16
#define UART_ECHOO_CHECK 0x40
/*
* reverse bits order lsb<->msb
*
* input:
* byte byte to reverse
* output:
* reversed byte
*/
static uint8_t reverse_byte( uint8_t byte )
{
byte = ((byte >> 1) & 0x55) | ((byte << 1) & 0xaa);
byte = ((byte >> 2) & 0x33) | ((byte << 2) & 0xcc);
byte = ((byte >> 4) & 0x0f) | ((byte << 4) & 0xf0);
return( byte );
}
/*
* initialize device
*
* input:
* device identifier (always 0)
* config uart configuration
* output:
* 0 if success, otherwise -1
*/
static int8_t uart_open( uint8_t device, uint8_t config )
{
return( -1 );
}
/*
* release device
*
* input:
* device identifier
* output:
* 0 if success, otherwise -1
*/
static int8_t uart_close( uint8_t device )
{
return( -1 );
}
/*
* read from device
*
* input:
* device identifier (always 0)
* byte address of byte to read
* output:
* 0 if success, otherwise -1
*/
static int8_t uart_read( uint8_t device, uint8_t* byte )
{
return( -1 );
}
/*
* write to device
*
* input:
* device identifier (always 0)
* byte byte to write
* output:
* 0 if success, otherwise -1
*/
static int8_t uart_write( uint8_t device, uint8_t byte )
{
return( -1 );
}
/*
* device special feature
*
* input:
* device identifier (always 0)
* request device dependent
* args list of arguments
* output:
* 0 if success, otherwise -1
*/
#ifdef UART_IOCTL
static int8_t uart_ioctl( uint8_t device, uint8_t request, va_list args )
{
return( -1 );
}
#endif
|