4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5 2011 Stephan Veigl <veig@gmx.net>
7 This file is part of simavr.
9 simavr is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 simavr 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.
19 You should have received a copy of the GNU General Public License
20 along with simavr. If not, see <http://www.gnu.org/licenses/>.
26 #include "avr_bitbang.h"
28 #include "sim_regbit.h"
30 #include "avr_ioport.h"
32 ///@todo refactor SPI to bitbang
34 #define BITBANG_MASK 0xFFFFFFFFUL
37 * read (sample) data from input pin
39 * @param p internal bitbang structure
41 static void avr_bitbang_read_bit(avr_bitbang_t *p)
43 avr_ioport_state_t iostate;
51 avr_ioctl(p->avr, AVR_IOCTL_IOPORT_GETSTATE( p->p_in.port ), &iostate);
52 bit = ( iostate.pin >> p->p_in.pin ) & 1;
54 if ( p->data_order ) {
55 // data order: shift right
56 p->data = (p->data >> 1) | ( bit << (p->buffer_size-1));
58 // data order: shift left
59 p->data = (p->data << 1) | bit;
65 if ( p->callback_bit_read ) {
66 p->callback_bit_read(bit, p->callback_param);
70 p->data = p->data & ~(BITBANG_MASK << p->buffer_size);
74 * write data to output pin
76 * @param p bitbang structure
78 static void avr_bitbang_write_bit(avr_bitbang_t *p)
85 if ( p->data_order ) {
86 // data order: shift right
89 // data order: shift left
90 bit = (p->data >> (p->buffer_size-1)) & 1;
94 if ( p->p_out.port ) {
95 avr_raise_irq(avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_out.port ), p->p_out.pin), bit);
99 if ( p->callback_bit_write ) {
100 p->callback_bit_write(bit, p->callback_param);
106 * process clock edges (both: positive and negative edges)
108 * @param p bitbang structure
111 static void avr_bitbang_clk_edge(avr_bitbang_t *p)
113 uint8_t phase = (p->clk_count & 1) ^ p->clk_phase;
114 uint8_t clk = (p->clk_count & 1) ^ p->clk_pol;
124 // generate clock output on HW pin
125 if ( p->clk_generate && p->p_clk.port ) {
126 avr_raise_irq(avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), clk);
131 avr_bitbang_read_bit(p);
135 avr_bitbang_write_bit(p);
138 if ( p->clk_count >= (p->buffer_size*2) ) {
140 if ( p->callback_transfer_finished ) {
141 p->data = p->callback_transfer_finished(p->data, p->callback_param);
147 static avr_cycle_count_t avr_bitbang_clk_timer(struct avr_t * avr, avr_cycle_count_t when, void * param)
149 avr_bitbang_t * p = (avr_bitbang_t *)param;
151 avr_bitbang_clk_edge(p);
154 return when + p->clk_cycles/2;
159 static void avr_bitbang_clk_hook(struct avr_irq_t * irq, uint32_t value, void * param)
161 avr_bitbang_t * p = (avr_bitbang_t *)param;
162 uint8_t clk = (p->clk_count & 1) ^ p->clk_pol;
168 avr_bitbang_clk_edge(p);
172 * reset bitbang sub-module
174 * @param avr avr attached to
175 * @param p bitbang structure
177 void avr_bitbang_reset(avr_t *avr, avr_bitbang_t * p)
184 if ( p->buffer_size < 1 || p->buffer_size > 32 ) {
186 "Error: bitbang buffer size should be between 1 and 32. set value: %d\n", p->buffer_size);
193 * start bitbang transfer
195 * buffers should be written / cleared in advanced
196 * timers and interrupts are connected
198 * @param p bitbang structure
200 void avr_bitbang_start(avr_bitbang_t * p)
205 if ( p->clk_phase == 0 ) {
207 avr_bitbang_write_bit(p);
210 if ( p->clk_generate ) {
211 // master mode, generate clock -> set timer
212 avr_cycle_timer_register(p->avr, (p->clk_cycles/2), avr_bitbang_clk_timer, p);
214 // slave mode -> attach clock function to clock pin
216 avr_irq_register_notify( avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), avr_bitbang_clk_hook, p);
223 * stop bitbang transfer
225 * timers and interrupts are disabled
227 * @param p bitbang structure
229 void avr_bitbang_stop(avr_bitbang_t * p)
233 avr_cycle_timer_cancel(p->avr, avr_bitbang_clk_timer, p);
234 avr_irq_unregister_notify( avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), avr_bitbang_clk_hook, p);