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/>.
23 #ifndef __AVR_BITBANG_H__
24 #define __AVR_BITBANG_H__
33 #include "avr_bitbang.h"
35 #include "sim_regbit.h"
37 #include "avr_ioport.h"
39 ///@todo refactor SPI to bitbang
41 #define BITBANG_MASK 0xFFFFFFFFUL
44 * read (sample) data from input pin
46 * @param p internal bitbang structure
48 static void avr_bitbang_read_bit(avr_bitbang_t *p)
50 avr_ioport_state_t iostate;
58 avr_ioctl(p->avr, AVR_IOCTL_IOPORT_GETSTATE( p->p_in.port ), &iostate);
59 bit = ( iostate.pin >> p->p_in.pin ) & 1;
61 if ( p->data_order ) {
62 // data order: shift right
63 p->data = (p->data >> 1) | ( bit << (p->buffer_size-1));
65 // data order: shift left
66 p->data = (p->data << 1) | bit;
72 if ( p->callback_bit_read ) {
73 p->callback_bit_read(bit, p->callback_param);
77 p->data = p->data & ~(BITBANG_MASK << p->buffer_size);
81 * write data to output pin
83 * @param p bitbang structure
85 static void avr_bitbang_write_bit(avr_bitbang_t *p)
92 if ( p->data_order ) {
93 // data order: shift right
96 // data order: shift left
97 bit = (p->data >> (p->buffer_size-1)) & 1;
101 if ( p->p_out.port ) {
102 avr_raise_irq(avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_out.port ), p->p_out.pin), bit);
106 if ( p->callback_bit_write ) {
107 p->callback_bit_write(bit, p->callback_param);
113 * process clock edges (both: positive and negative edges)
115 * @param p bitbang structure
118 static void avr_bitbang_clk_edge(avr_bitbang_t *p)
120 uint8_t phase = (p->clk_count & 1) ^ p->clk_phase;
121 uint8_t clk = (p->clk_count & 1) ^ p->clk_pol;
131 // generate clock output on HW pin
132 if ( p->clk_generate && p->p_clk.port ) {
133 avr_raise_irq(avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), clk);
138 avr_bitbang_read_bit(p);
142 avr_bitbang_write_bit(p);
145 if ( p->clk_count >= (p->buffer_size*2) ) {
147 if ( p->callback_transfer_finished ) {
148 p->data = p->callback_transfer_finished(p->data, p->callback_param);
154 static avr_cycle_count_t avr_bitbang_clk_timer(struct avr_t * avr, avr_cycle_count_t when, void * param)
156 avr_bitbang_t * p = (avr_bitbang_t *)param;
158 avr_bitbang_clk_edge(p);
161 return when + p->clk_cycles/2;
166 static void avr_bitbang_clk_hook(struct avr_irq_t * irq, uint32_t value, void * param)
168 avr_bitbang_t * p = (avr_bitbang_t *)param;
169 uint8_t clk = (p->clk_count & 1) ^ p->clk_pol;
175 avr_bitbang_clk_edge(p);
179 * reset bitbang sub-module
181 * @param avr avr attached to
182 * @param p bitbang structure
184 void avr_bitbang_reset(avr_t *avr, avr_bitbang_t * p)
191 if ( p->buffer_size < 1 || p->buffer_size > 32 ) {
193 "Error: bitbang buffer size should be between 1 and 32. set value: %d\n", p->buffer_size);
200 * start bitbang transfer
202 * buffers should be written / cleared in advanced
203 * timers and interrupts are connected
205 * @param p bitbang structure
207 void avr_bitbang_start(avr_bitbang_t * p)
212 if ( p->clk_phase == 0 ) {
214 avr_bitbang_write_bit(p);
217 if ( p->clk_generate ) {
218 // master mode, generate clock -> set timer
219 avr_cycle_timer_register(p->avr, (p->clk_cycles/2), avr_bitbang_clk_timer, p);
221 // slave mode -> attach clock function to clock pin
223 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);
230 * stop bitbang transfer
232 * timers and interrupts are disabled
234 * @param p bitbang structure
236 void avr_bitbang_stop(avr_bitbang_t * p)
240 avr_cycle_timer_cancel(p->avr, avr_bitbang_clk_timer, p);
241 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);
248 #endif /*__AVR_BITBANG_H__*/