~arcachofo/simulide/1.1.0

« back to all changes in this revision

Viewing changes to src/simavr/sim/avr_spi.c

  • Committer: arcachofo
  • Date: 2021-01-01 14:23:42 UTC
  • Revision ID: arcachofo@simulide.com-20210101142342-ozfljnll44g5lbl3
Initial Commit 0.5.15-RC3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
        avr_spi.c
 
3
 
 
4
        Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
 
5
 
 
6
        This file is part of simavr.
 
7
 
 
8
        simavr is free software: you can redistribute it and/or modify
 
9
        it under the terms of the GNU General Public License as published by
 
10
        the Free Software Foundation, either version 3 of the License, or
 
11
        (at your option) any later version.
 
12
 
 
13
        simavr is distributed in the hope that it will be useful,
 
14
        but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
        GNU General Public License for more details.
 
17
 
 
18
        You should have received a copy of the GNU General Public License
 
19
        along with simavr.  If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
#include <stdio.h>
 
23
#include "avr_spi.h"
 
24
#include "sim_gdb.h"
 
25
 
 
26
static avr_cycle_count_t avr_spi_raise( avr_spi_t* p)
 
27
{
 
28
    if( avr_regbit_get(p->bit_bang.avr, p->spe) )
 
29
    {
 
30
                avr_raise_interrupt(p->bit_bang.avr, &p->spi);
 
31
        if( avr_regbit_get(p->bit_bang.avr, p->mstr) )
 
32
        {
 
33
                        avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, p->output_data_register);
 
34
                }
 
35
        }
 
36
        return 0;
 
37
}
 
38
 
 
39
static uint32_t avr_spi_transfer_finished( uint32_t data, void* param )
 
40
{
 
41
    avr_spi_t* p = (avr_spi_t *)param;
 
42
    if( p->bit_bang.clk_generate ) avr_bitbang_stop( &(p->bit_bang) );
 
43
 
 
44
        p->input_data_register = data & 0xFF;
 
45
    avr_spi_raise( p );
 
46
 
 
47
    // MOSI PIN High when idle
 
48
    avr_raise_irq(avr_io_getirq(p->bit_bang.avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_mosi.port ), p->p_mosi.pin), 1);
 
49
        return data;
 
50
}
 
51
 
 
52
static void avr_spi_bitbang_switch_mode( avr_spi_t* p, uint8_t master )
 
53
{
 
54
    if( master )
 
55
    {
 
56
        p->bit_bang.p_in  = p->p_miso;
 
57
                p->bit_bang.p_out = p->p_mosi;
 
58
        avr_irq_t* irq;
 
59
                uint32_t irq_val;
 
60
        irq = avr_io_getirq( p->bit_bang.avr, AVR_IOCTL_IOPORT_GETIRQ(p->p_miso.port), IOPORT_IRQ_DIRECTION_ALL );
 
61
                irq_val = irq->value & (1 << p->p_miso.pin);
 
62
        avr_raise_irq( irq, irq_val );
 
63
        // MOSI PIN High when idle
 
64
        avr_raise_irq(avr_io_getirq(p->bit_bang.avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_mosi.port ), p->p_mosi.pin), 1);
 
65
                p->bit_bang.clk_generate = 1;
 
66
    }
 
67
    else
 
68
    {
 
69
        p->bit_bang.p_in  = p->p_mosi;
 
70
                p->bit_bang.p_out = p->p_miso;
 
71
 
 
72
        avr_irq_t* irq;
 
73
                uint32_t irq_val;
 
74
        irq = avr_io_getirq( p->bit_bang.avr, AVR_IOCTL_IOPORT_GETIRQ(p->bit_bang.p_clk.port), IOPORT_IRQ_DIRECTION_ALL );
 
75
                irq_val = irq->value & (1 << p->bit_bang.p_clk.pin);
 
76
        avr_raise_irq( irq, irq_val );
 
77
 
 
78
        irq = avr_io_getirq( p->bit_bang.avr, AVR_IOCTL_IOPORT_GETIRQ(p->p_mosi.port), IOPORT_IRQ_DIRECTION_ALL );
 
79
                irq_val = irq->value & (1 << p->p_mosi.pin);
 
80
        avr_raise_irq( irq, irq_val );
 
81
 
 
82
        irq = avr_io_getirq( p->bit_bang.avr, AVR_IOCTL_IOPORT_GETIRQ(p->p_ss.port), IOPORT_IRQ_DIRECTION_ALL );
 
83
                irq_val = irq->value & (1 << p->p_ss.pin);
 
84
        avr_raise_irq( irq, irq_val );
 
85
 
 
86
                p->bit_bang.clk_generate = 0;
 
87
        }
 
88
}
 
89
 
 
90
static uint8_t avr_spi_read( struct avr_t* avr, avr_io_addr_t addr, void* param)
 
91
{
 
92
    avr_spi_t* p = (avr_spi_t*)param;
 
93
        uint8_t v = p->input_data_register;
 
94
        p->input_data_register = 0;
 
95
        avr_regbit_clear(avr, p->spi.raised);
 
96
//      printf("avr_spi_read = %02x\n", v);
 
97
        return v;
 
98
}
 
99
 
 
100
static void avr_spi_write( struct avr_t* avr, avr_io_addr_t addr, uint8_t v, void* param)
 
101
{
 
102
    avr_spi_t* p = (avr_spi_t *)param;
 
103
 
 
104
    if (addr == p->r_spdr)
 
105
    {
 
106
                /* Clear the SPIF bit. See ATmega164/324/644 manual, Section 18.5.2. */
 
107
        avr_regbit_clear( avr, p->spi.raised );
 
108
 
 
109
                // The byte to be sent should NOT be written there,
 
110
                // the value written could never be read back.
 
111
                //avr_core_watch_write(avr, addr, v);
 
112
                p->output_data_register = v;
 
113
        if (avr->gdb) avr_gdb_handle_watchpoints(avr, addr, AVR_GDB_WATCH_WRITE);
 
114
 
 
115
        if (avr_regbit_get(avr, p->spe))
 
116
        {
 
117
                        avr_bitbang_stop(&(p->bit_bang));
 
118
                        avr_bitbang_reset(avr, &(p->bit_bang));
 
119
                        p->bit_bang.data = v;
 
120
 
 
121
            if (avr_regbit_get(avr, p->mstr))
 
122
            {
 
123
                                p->bit_bang.clk_generate = 1;
 
124
                                avr_bitbang_start(&(p->bit_bang));
 
125
            }
 
126
            else
 
127
            {
 
128
                                p->bit_bang.clk_generate = 0;
 
129
                        }
 
130
                }
 
131
    }
 
132
    else if ((addr == p->r_spcr) || (addr == p->r_spsr))
 
133
    {
 
134
                avr_core_watch_write(avr, addr, v);
 
135
                avr_bitbang_stop(&(p->bit_bang));
 
136
                avr_bitbang_reset(avr, &(p->bit_bang));
 
137
 
 
138
        if (avr_regbit_get(avr, p->spe))
 
139
        {
 
140
            p->bit_bang.clk_phase  = avr_regbit_get( avr, p->cpha );
 
141
            p->bit_bang.clk_pol    = avr_regbit_get( avr, p->cpol );
 
142
            p->bit_bang.data_order = avr_regbit_get( avr, p->dord );
 
143
 
 
144
            if( avr_regbit_get( avr, p->mstr ))
 
145
            {
 
146
                                int clock_divider_ix = (avr_regbit_get(avr, p->spr[0]) | avr_regbit_get(avr, p->spr[1]));
 
147
                                int clock_divider = 1;
 
148
                switch( clock_divider_ix )
 
149
                {
 
150
                                        case 0:
 
151
                                                clock_divider = 4;
 
152
                                                break;
 
153
                                        case 1:
 
154
                                                clock_divider = 16;
 
155
                                                break;
 
156
                                        case 2:
 
157
                                                clock_divider = 64;
 
158
                                                break;
 
159
                                        case 3:
 
160
                                                clock_divider = 128;
 
161
                                                break;
 
162
                                }
 
163
                if( avr_regbit_get(avr, p->spr[2]) ) clock_divider /= 2;
 
164
 
 
165
                                p->bit_bang.clk_cycles = clock_divider;
 
166
                avr_spi_bitbang_switch_mode( p, 1 );
 
167
            }
 
168
            else
 
169
            {
 
170
                avr_spi_bitbang_switch_mode( p, 0 );
 
171
                        }
 
172
                }
 
173
        }
 
174
}
 
175
 
 
176
static void avr_spi_ss_hook( struct avr_irq_t * irq, uint32_t value, void * param)
 
177
{
 
178
    avr_spi_t* p = (avr_spi_t*)param;
 
179
 
 
180
    if( avr_regbit_get(p->bit_bang.avr, p->mstr) )  // master mode
 
181
    {
 
182
                avr_ioport_state_t iostate;
 
183
                uint8_t dir = 0;
 
184
 
 
185
                avr_ioctl(p->bit_bang.avr, AVR_IOCTL_IOPORT_GETSTATE( p->p_ss.port ), &iostate);
 
186
                dir = ( iostate.ddr >> p->p_ss.pin ) & 1;
 
187
        if( !dir )
 
188
        {
 
189
            if( !value ) // other master is active, reset to slave mode
 
190
            {
 
191
                avr_bitbang_stop( &(p->bit_bang) );
 
192
                avr_bitbang_reset( p->bit_bang.avr, &(p->bit_bang) );
 
193
                avr_regbit_setto( p->bit_bang.avr, p->mstr, 0);
 
194
                avr_spi_bitbang_switch_mode( p, 0);
 
195
                                avr_spi_raise(p);
 
196
                        }
 
197
                }
 
198
    }
 
199
    else // slave mode
 
200
    {
 
201
        if (value)
 
202
        {
 
203
                        avr_bitbang_stop(&(p->bit_bang));
 
204
                        avr_bitbang_reset(p->bit_bang.avr, &(p->bit_bang));
 
205
                }
 
206
        }
 
207
}
 
208
 
 
209
static void avr_spi_irq_input( struct avr_irq_t * irq, uint32_t value, void * param)
 
210
{
 
211
        avr_spi_t * p = (avr_spi_t *)param;
 
212
        avr_t * avr = p->io.avr;
 
213
 
 
214
        // check to see if receiver is enabled
 
215
    if (!avr_regbit_get(avr, p->spe)) return;
 
216
 
 
217
        // double buffer the input.. ?
 
218
        p->input_data_register = value;
 
219
        avr_raise_interrupt(avr, &p->spi);
 
220
 
 
221
        // if in slave mode, 
 
222
        // 'output' the byte only when we received one...
 
223
    if (!avr_regbit_get(avr, p->mstr)) avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]);
 
224
}
 
225
 
 
226
void avr_spi_reset( struct avr_io_t* io)
 
227
{
 
228
    avr_spi_t* p = (avr_spi_t*)io;
 
229
        avr_bitbang_reset(p->bit_bang.avr, &(p->bit_bang));
 
230
        avr_irq_register_notify(p->io.irq + SPI_IRQ_INPUT, avr_spi_irq_input, p);
 
231
}
 
232
 
 
233
static const char * irq_names[SPI_IRQ_COUNT] = {
 
234
        [SPI_IRQ_INPUT] = "8<in",
 
235
        [SPI_IRQ_OUTPUT] = "8<out",
 
236
};
 
237
 
 
238
static  avr_io_t        _io = {
 
239
        .kind = "spi",
 
240
        .reset = avr_spi_reset,
 
241
        .irq_names = irq_names,
 
242
};
 
243
 
 
244
void avr_spi_init( avr_t* avr, avr_spi_t* p)
 
245
{
 
246
        p->io = _io;
 
247
 
 
248
        p->bit_bang.avr = avr;
 
249
        p->bit_bang.callback_transfer_finished = avr_spi_transfer_finished;
 
250
        p->bit_bang.callback_param = p;
 
251
        p->bit_bang.buffer_size = 8;
 
252
 
 
253
        avr_register_io(avr, &p->io);
 
254
        avr_register_vector(avr, &p->spi);
 
255
        // allocate this module's IRQ
 
256
        avr_io_setirqs(&p->io, AVR_IOCTL_SPI_GETIRQ(p->name), SPI_IRQ_COUNT, NULL);
 
257
 
 
258
        avr_register_io_write(avr, p->r_spdr, avr_spi_write, p);
 
259
        avr_register_io_write(avr, p->r_spcr, avr_spi_write, p);
 
260
        avr_register_io_write(avr, p->r_spsr, avr_spi_write, p);
 
261
        avr_register_io_read(avr, p->r_spdr, avr_spi_read, p);
 
262
 
 
263
        avr_irq_register_notify( avr_io_getirq(p->bit_bang.avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_ss.port ), p->p_ss.pin),
 
264
                                                         avr_spi_ss_hook, p);
 
265
}
 
266