/*ARGSUSED*/ int i2c_bitbang_send_stop(void *v, int flags, i2c_bitbang_ops_t ops) { BB_DIR(OUTPUT); BB_SET( SCL); delay(4); /* stop setup time (4.0 uS) */ BB_SET(SDA | SCL); return (0); }
/*ARGSUSED*/ int i2c_bitbang_send_start(void *v, int flags, i2c_bitbang_ops_t ops) { BB_DIR(OUTPUT); BB_SET(SDA | SCL); delay(5); /* bus free time (4.7 uS) */ BB_SET( SCL); delay(4); /* start hold time (4.0 uS) */ BB_SET( 0); delay(5); /* clock low time (4.7 uS) */ return (0); }
int i2c_bitbang_write_byte(void *v, uint8_t val, int flags, i2c_bitbang_ops_t ops) { uint32_t bit; uint8_t mask; int error; BB_DIR(OUTPUT); for (mask = 0x80; mask != 0; mask >>= 1) { bit = (val & mask) ? SDA : 0; BB_SET(bit ); delay(1); /* data setup time (250 nS) */ BB_SET(bit | SCL); delay(4); /* clock high time (4.0 uS) */ BB_SET(bit ); delay(5); /* clock low time (4.7 uS) */ } BB_DIR(INPUT); BB_SET(SDA ); delay(5); BB_SET(SDA | SCL); delay(4); error = (BB_READ & SDA) ? EIO : 0; BB_SET(SDA ); delay(5); if (flags & I2C_F_STOP) (void) i2c_bitbang_send_stop(v, flags, ops); return (error); }
/*---------------------------------------------------------------------------*/ const struct mac_driver * xmac_init(const struct radio_driver *d) { #if WITH_TIMETABLE timetable_clear(&xmac_timetable); #endif radio_is_on = 0; waiting_for_packet = 0; PT_INIT(&pt); rtimer_set(&rt, RTIMER_NOW() + xmac_config.off_time, 1, TC(powercycle), NULL); xmac_is_on = 1; radio = d; radio->set_receive_function(input_packet); BB_SET("xmac.state_addr", (int) &waiting_for_packet); BB_SET(XMAC_RECEIVER, 0); BB_SET(XMAC_STROBES, 0); BB_SET(XMAC_SEND_WITH_ACK, 0); BB_SET(XMAC_SEND_WITH_NOACK, 0); return &xmac_driver; }
int i2c_bitbang_read_byte(void *v, uint8_t *valp, int flags, i2c_bitbang_ops_t ops) { int i; uint8_t val = 0; uint32_t bit; BB_DIR(INPUT); BB_SET(SDA ); for (i = 0; i < 8; i++) { val <<= 1; BB_SET(SDA | SCL); if (i2c_wait_for_scl(v, ops) != 0) return (EIO); delay(4); /* clock high time (4.0 uS) */ if (BB_READ & SDA) val |= 1; BB_SET(SDA ); delay(5); /* clock low time (4.7 uS) */ } bit = (flags & I2C_F_LAST) ? SDA : 0; BB_DIR(OUTPUT); BB_SET(bit ); delay(1); /* data setup time (250 nS) */ BB_SET(bit | SCL); if (i2c_wait_for_scl(v, ops) != 0) return (EIO); delay(4); /* clock high time (4.0 uS) */ BB_SET(bit ); delay(5); /* clock low time (4.7 uS) */ BB_DIR(INPUT); BB_SET(SDA ); delay(5); if ((flags & (I2C_F_STOP | I2C_F_LAST)) == (I2C_F_STOP | I2C_F_LAST)) (void) i2c_bitbang_send_stop(v, flags, ops); *valp = val; return (0); }
/*---------------------------------------------------------------------------*/ static int send_packet(void) { rtimer_clock_t t0; rtimer_clock_t t; int strobes; struct xmac_hdr *hdr; int got_ack = 0; struct xmac_hdr msg; int len; int is_broadcast = 0; #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send"); #endif #if WITH_CHANNEL_CHECK /* Check if there are other strobes in the air. */ waiting_for_packet = 1; on(); t0 = RTIMER_NOW(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_wait_time * 2)) { len = radio->read(&msg, sizeof(msg)); if(len > 0) { someone_is_sending = 1; } } waiting_for_packet = 0; while(someone_is_sending); /* {printf("z");}*/ #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send 2"); #endif /* WITH_TIMETABLE */ #endif /* WITH_CHANNEL_CHECK */ /* By setting we_are_sending to one, we ensure that the rtimer powercycle interrupt do not interfere with us sending the packet. */ we_are_sending = 1; off(); rimebuf_hdralloc(sizeof(struct xmac_hdr)); hdr = rimebuf_hdrptr(); rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr); rimeaddr_copy(&hdr->receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER)); if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { is_broadcast = 1; } rimebuf_compact(); t0 = RTIMER_NOW(); strobes = 0; BB_SET(XMAC_RECEIVER, hdr->receiver.u16[0]); LEDS_ON(LEDS_BLUE); /* Send a train of strobes until the receiver answers with an ACK. */ /* Turn on the radio to listen for the strobe ACK. */ if(!is_broadcast) { on(); } watchdog_stop(); got_ack = 0; for(strobes = 0; got_ack == 0 && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_time); strobes++) { t = RTIMER_NOW(); rimeaddr_copy(&msg.sender, &rimeaddr_node_addr); rimeaddr_copy(&msg.receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER)); #if WITH_TIMETABLE if(rimeaddr_cmp(&msg.receiver, &rimeaddr_null)) { TIMETABLE_TIMESTAMP(xmac_timetable, "send broadcast strobe"); } else { TIMETABLE_TIMESTAMP(xmac_timetable, "send strobe"); } #endif if(is_broadcast) { /* If we are sending a broadcast, we don't send strobes, we simply send the data packet repetedly */ radio->send(rimebuf_hdrptr(), rimebuf_totlen()); } else { /* Send the strobe packet. */ radio->send((const uint8_t *)&msg, sizeof(struct xmac_hdr)); } CPRINTF("+"); while(got_ack == 0 && RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) { /* See if we got an ACK */ len = radio->read((uint8_t *)&msg, sizeof(struct xmac_hdr)); if(len > 0) { CPRINTF("_"); if(rimeaddr_cmp(&msg.sender, &rimeaddr_node_addr) && rimeaddr_cmp(&msg.receiver, &rimeaddr_node_addr)) { #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send ack received"); #endif CPRINTF("@"); /* We got an ACK from the receiver, so we can immediately send the packet. */ got_ack = 1; } } } /* XXX: turn off radio if we haven't heard an ACK within a specified time interval. */ /* if(got_ack == 0) { off(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)); on(); }*/ } if(got_ack /* XXX && needs_ack */) { #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send got ack"); #endif on(); /* Wait for possible ACK packet */ } else if(!is_broadcast) { #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send no ack received"); #endif on(); /* shell ping don't seem to work with off() here, so we'll keep it on() for a while. */ } /* Send the data packet. */ if(is_broadcast || got_ack) { #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send packet"); #endif radio->send(rimebuf_hdrptr(), rimebuf_totlen()); CPRINTF("#"); } watchdog_start(); PRINTF("xmac: send (strobes=%u,len=%u,%s), done\n", strobes, rimebuf_totlen(), got_ack ? "ack" : "no ack"); BB_SET(XMAC_STROBES, strobes); if(got_ack) { BB_INC(XMAC_SEND_WITH_ACK, 1); } else { BB_INC(XMAC_SEND_WITH_NOACK, 1); } /* printf("Strobe %d got_ack %d\n", strobes, got_ack);*/ we_are_sending = 0; #if WITH_TIMETABLE TIMETABLE_TIMESTAMP(xmac_timetable, "send we_are_sending = 0"); #endif LEDS_OFF(LEDS_BLUE); return 1; }