From d9656de88f7af77b39bfe9985f0ac7c623932d71 Mon Sep 17 00:00:00 2001 From: Nicholas Corgan Date: Tue, 30 Jun 2015 13:36:15 -0700 Subject: OctoClock bugfixes * Bumped compatibility version to 3 * firmware: Ethernet, clkdist bugfixes * lib: fixed invalid rev detection --- firmware/octoclock/lib/clkdist.c | 14 +- firmware/octoclock/lib/enc28j60.c | 488 +++++++++++++--------------------- firmware/octoclock/lib/init.c | 6 +- firmware/octoclock/lib/network.c | 40 ++- firmware/octoclock/lib/state.c | 102 +++---- firmware/octoclock/lib/udp_handlers.c | 37 ++- firmware/octoclock/lib/usart.c | 8 - 7 files changed, 267 insertions(+), 428 deletions(-) (limited to 'firmware/octoclock/lib') diff --git a/firmware/octoclock/lib/clkdist.c b/firmware/octoclock/lib/clkdist.c index ed29510b6..0468ac38e 100644 --- a/firmware/octoclock/lib/clkdist.c +++ b/firmware/octoclock/lib/clkdist.c @@ -21,6 +21,8 @@ #include #include +#include + #define wait() for(uint16_t u=14000; u; u--) asm("nop"); #define CLK (PA0) // Shift by 0 bits @@ -33,7 +35,7 @@ // Table of 32-bit constants to be written to the TI chip's registers. These are // from the "Special Settings" on Page 35 of the datasheet. // For the GPS's 10 MHz output -static uint32_t table_Pri_Ref[] = { +static const uint32_t table_Pri_Ref[] = { Bits_32(1,01010100,0,0), // Reg 0 Bits_32(1,01010100,0,0), // Outputs LVCMOS Positive&Negative Active - Non-inverted Bits_32(1,01010100,0,0), @@ -47,7 +49,7 @@ static uint32_t table_Pri_Ref[] = { // For the External 10 MHz input LVDS with external termination, // Effectively DC coupled -static uint32_t table_Sec_Ref[] = { +static const uint32_t table_Sec_Ref[] = { Bits_32(0001,01010100,0,100000), // Reg 0 -- use Secondary Reference for all channels Bits_32(0001,01010100,0,100000), // Outputs LVCMOS Positive&Negative Active - Non-inverted Bits_32(0001,01010100,0,100000), @@ -81,7 +83,6 @@ static bool get_bit(uint8_t bit_number) { // Send 32 bits to TI chip, LSB first. // Don't worry about reading any bits back at this time static void send_SPI(uint32_t bits) { - // Basically, when the clock is low, one can set MOSI to anything, as it's // ignored. set_bit(CE_, Lo); // Start SPI transaction with TI chip @@ -130,7 +131,8 @@ void setup_TI_CDCE18005(TI_Input_10_MHz which_input) { for(uint8_t i=0; i. + */ #include #include -#include -#include #include -u08 Enc28j60Bank; -u16 NextPacketPtr; - -u08 enc28j60ReadOp(u08 op, u08 address) -{ - u08 data; - - // assert CS - ENC28J60_CONTROL_PORT &= ~(1<>5); - Enc28j60Bank = (address & BANK_MASK); - } +static void enc28j60_read_buffer(uint8_t* buf, uint16_t len){ + SET_CS_ACTIVE(); + + SPDR = RBM; + SPI_WAIT(); + while(len){ + len--; + SPDR = 0x00; + SPI_WAIT(); + *buf = SPDR; + buf++; + } + *buf = '\0'; + + SET_CS_PASSIVE(); } -u08 enc28j60Read(u08 address) -{ - // set the bank - enc28j60SetBank(address); - // do the read - return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address); +static void enc28j60_write_buffer(uint8_t* buf, uint16_t len){ + SET_CS_ACTIVE(); + + SPDR = WBM; + SPI_WAIT(); + while(len){ + len--; + SPDR = *buf; + buf++; + SPI_WAIT(); + } + + SET_CS_PASSIVE(); } -void enc28j60Write(u08 address, u08 data) -{ - // set the bank - enc28j60SetBank(address); - // do the write - enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data); +static void enc28j60_set_bank(uint8_t addr){ + if((addr & BANK_MASK) != current_bank){ + enc28j60_write_op(BFC, ECON1, (BSEL1|BSEL0)); + enc28j60_write_op(BFS, ECON1, ((addr & BANK_MASK) >> 5)); + current_bank = (addr & BANK_MASK); + } } -u16 enc28j60PhyRead(u08 address) -{ - u16 data; - - // Set the right address and start the register read operation - enc28j60Write(MIREGADR, address); - enc28j60Write(MICMD, MICMD_MIIRD); - - // wait until the PHY read completes - while(enc28j60Read(MISTAT) & MISTAT_BUSY); - - // quit reading - enc28j60Write(MICMD, 0x00); - - // get data value - data = enc28j60Read(MIRDL); - data |= enc28j60Read(MIRDH); - // return the data - return data; +static uint8_t enc28j60_read(uint8_t addr){ + enc28j60_set_bank(addr); + return enc28j60_read_op(RCR, addr); } -void enc28j60PhyWrite(u08 address, u16 data) -{ - // set the PHY register address - enc28j60Write(MIREGADR, address); - - // write the PHY data - enc28j60Write(MIWRL, data); - enc28j60Write(MIWRH, data>>8); - - // wait until the PHY write completes - while(enc28j60Read(MISTAT) & MISTAT_BUSY); +static void enc28j60_write(uint8_t addr, uint16_t value){ + enc28j60_set_bank(addr); + enc28j60_write_op(WCR, addr, value); } -void enc28j60Init(u08* macaddr) -{ - // initialize I/O - sbi(ENC28J60_CONTROL_DDR, ENC28J60_CONTROL_CS); - sbi(ENC28J60_CONTROL_PORT, ENC28J60_CONTROL_CS); - - // setup SPI I/O pins - sbi(ENC28J60_SPI_PORT, ENC28J60_SPI_SCK); // set SCK hi - sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_SCK); // set SCK as output - cbi(ENC28J60_SPI_DDR, ENC28J60_SPI_MISO); // set MISO as input - sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_MOSI); // set MOSI as output - sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_SS); // SS must be output for Master mode to work - // initialize SPI interface - // master mode - sbi(SPCR, MSTR); - // select clock phase positive-going in middle of data - cbi(SPCR, CPOL); - // Data order MSB first - cbi(SPCR,DORD); - // switch to f/4 2X = f/2 bitrate - cbi(SPCR, SPR0); - cbi(SPCR, SPR1); - sbi(SPSR, SPI2X); - // enable SPI - sbi(SPCR, SPE); - - // perform system reset - enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); - - /* - * "After sending an SPI Reset command, the PHY - * clock is stopped but the ESTAT.CLKRDY bit is not - * cleared. Therefore, polling the CLKRDY bit will not - * work to detect if the PHY is ready. - * - * Additionally, the hardware start-up time of 300 us - * may expire before the device is ready to operate. - * - * Work around - * After issuing the Reset command, wait at least - * 1 ms in firmware for the device to be ready." - * - * Source: http://ww1.microchip.com/downloads/en/DeviceDoc/80349c.pdf - */ - _delay_ms(1); - - // do bank 0 stuff - // initialize receive buffer - // 16-bit transfers, must write low byte first - // set receive buffer start address - NextPacketPtr = RXSTART_INIT; - enc28j60Write(ERXSTL, RXSTART_INIT&0xFF); - enc28j60Write(ERXSTH, RXSTART_INIT>>8); - // set receive pointer address - enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF); - enc28j60Write(ERXRDPTH, RXSTART_INIT>>8); - // set receive buffer end - // ERXND defaults to 0x1FFF (end of ram) - enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF); - enc28j60Write(ERXNDH, RXSTOP_INIT>>8); - // set transmit buffer start - // ETXST defaults to 0x0000 (beginnging of ram) - enc28j60Write(ETXSTL, TXSTART_INIT&0xFF); - enc28j60Write(ETXSTH, TXSTART_INIT>>8); - - // do bank 2 stuff - // enable MAC receive - enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); - // bring MAC out of reset - enc28j60Write(MACON2, 0x00); - // enable automatic padding and CRC operations - enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); - // set inter-frame gap (non-back-to-back) - enc28j60Write(MAIPGL, 0x12); - enc28j60Write(MAIPGH, 0x0C); - // set inter-frame gap (back-to-back) - enc28j60Write(MABBIPG, 0x12); - // Set the maximum packet size which the controller will accept - enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF); - enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8); - - // do bank 3 stuff - // write MAC address - // NOTE: MAC address in ENC28J60 is byte-backward - enc28j60Write(MAADR5, macaddr[0]); - enc28j60Write(MAADR4, macaddr[1]); - enc28j60Write(MAADR3, macaddr[2]); - enc28j60Write(MAADR2, macaddr[3]); - enc28j60Write(MAADR1, macaddr[4]); - enc28j60Write(MAADR0, macaddr[5]); - - // no loopback of transmitted frames - enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS); - - // switch to bank 0 - enc28j60SetBank(ECON1); - // enable interrutps - enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); - // enable packet reception - enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); +void enc28j60_init(uint8_t* mac_addr){ + SPI_DDR |= (1 << SPI_CS); + SET_CS_PASSIVE(); + + SPI_DDR |= ((1 << SPI_MOSI) | (1 << SPI_SCK)); + SPI_DDR &= ~(1 << SPI_MISO); + SPI_PORT &= ~(1 << SPI_MOSI); + SPI_PORT &= ~(1 << SPI_SCK); + SPCR = ((1 << SPE) | (1 << MSTR)); + SPSR |= (1 << SPI2X); + enc28j60_write_op(SC, 0, SC); + next_pkt_ptr = RXSTART_INIT; + + // Designate RX addresses + enc28j60_write(ERXSTL, (RXSTART_INIT & 0xFF)); + enc28j60_write(ERXSTH, (RXSTART_INIT >> 8)); + enc28j60_write(ERXNDL, (RXSTOP_INIT & 0xFF)); + enc28j60_write(ERXNDH, (RXSTOP_INIT >> 8)); + + // Designate TX addresses + enc28j60_write(ETXSTL, (TXSTART_INIT & 0xFF)); + enc28j60_write(ETXSTH, (TXSTART_INIT >> 8)); + enc28j60_write(ETXNDL, (TXSTOP_INIT & 0xFF)); + enc28j60_write(ETXNDH, (TXSTOP_INIT >> 8)); + + // Configure filters + enc28j60_write(ERXFCON, (UCEN|CRCEN|PMEN|BCEN)); + enc28j60_write(EPMM0, 0x3F); + enc28j60_write(EPMM1, 0x30); + enc28j60_write(EPMCSL, 0xF9); + enc28j60_write(EPMCSH, 0xF7); + + // MAC initialization + enc28j60_write(MACON1, (MARXEN|TXPAUS|RXPAUS)); + enc28j60_write(MACON2, 0x00); + enc28j60_write_op(BFS, MACON3, (PADCFG0|TXCRCEN|FRMLNEN)); + enc28j60_write(MAIPGL, 0x12); + enc28j60_write(MAIPGH, 0x0C); + enc28j60_write(MABBIPG, 0x12); + enc28j60_write(MAMXFLL, (MAX_FRAMELEN & 0xFF)); + enc28j60_write(MAMXFLH, (MAX_FRAMELEN >> 8)); + enc28j60_write(MAADR5, mac_addr[0]); + enc28j60_write(MAADR4, mac_addr[1]); + enc28j60_write(MAADR3, mac_addr[2]); + enc28j60_write(MAADR2, mac_addr[3]); + enc28j60_write(MAADR1, mac_addr[4]); + enc28j60_write(MAADR0, mac_addr[5]); + + enc28j60_set_bank(ECON1); + enc28j60_write_op(BFS, ECON1, ENCRXEN); } -void enc28j60PacketSend(unsigned int len1, unsigned char* packet1, unsigned int len2, unsigned char* packet2) -{ - //Errata: Transmit Logic reset - enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST); - enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST); - - // Set the write pointer to start of transmit buffer area - enc28j60Write(EWRPTL, TXSTART_INIT&0xff); - enc28j60Write(EWRPTH, TXSTART_INIT>>8); - // Set the TXND pointer to correspond to the packet size given - enc28j60Write(ETXNDL, (TXSTART_INIT+len1+len2)); - enc28j60Write(ETXNDH, (TXSTART_INIT+len1+len2)>>8); - - // write per-packet control byte - enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00); - - // copy the packet into the transmit buffer - enc28j60WriteBuffer(len1, packet1); - if(len2>0) enc28j60WriteBuffer(len2, packet2); - - // send the contents of the transmit buffer onto the network - enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); +uint16_t enc28j60_recv(uint8_t* buf, uint16_t max_len){ + uint16_t rxstat, len; + + // Return if no data is available + if(enc28j60_read(EPKTCNT) == 0) return 0; + + enc28j60_write(ERDPTL, (next_pkt_ptr & 0xFF)); + enc28j60_write(ERDPTH, (next_pkt_ptr >> 8)); + next_pkt_ptr = enc28j60_read_op(RBM, 0) | ((uint16_t)enc28j60_read_op(RBM, 0) << 8); + len = enc28j60_read_op(RBM, 0) | ((uint16_t)enc28j60_read_op(RBM, 0) << 8); + len -= 4; + rxstat = enc28j60_read_op(RBM, 0) | ((uint16_t)enc28j60_read_op(RBM, 0) << 8); + + // Length sanity check and actual enc28j60_read call + if(len > (max_len - 1)) len = max_len - 1; + if((rxstat & 0x80) == 0) len = 0; + else enc28j60_read_buffer(buf, len); + + // Update next packet pointer + enc28j60_write(ERXRDPTL, (next_pkt_ptr & 0xFF)); + enc28j60_write(ERXRDPTH, (next_pkt_ptr >> 8)); + if(((next_pkt_ptr - 1) < RXSTART_INIT) || ((next_pkt_ptr - 1) > RXSTOP_INIT)){ + enc28j60_write(ERXRDPTL, (RXSTOP_INIT & 0xFF)); + enc28j60_write(ERXRDPTH, (RXSTOP_INIT >> 8)); + } + else{ + enc28j60_write(ERXRDPTL, ((next_pkt_ptr - 1) & 0xFF)); + enc28j60_write(ERXRDPTH, ((next_pkt_ptr - 1) >> 8)); + } + enc28j60_write_op(BFS, ECON2, PKTDEC); + + return len; } -unsigned int enc28j60PacketReceive(unsigned int maxlen, u08* buf) -{ - u16 rxstat; - u16 len; - - // check if a packet has been received and buffered - if( !enc28j60Read(EPKTCNT) ) - return 0; - - // Set the read pointer to the start of the received packet - enc28j60Write(ERDPTL, (NextPacketPtr)); - enc28j60Write(ERDPTH, (NextPacketPtr)>>8); - // read the next packet pointer - NextPacketPtr = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); - NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; - // read the packet length - len = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); - len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; - // read the receive status - rxstat = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); - rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; - - // limit retrieve length - // (we reduce the MAC-reported length by 4 to remove the CRC) - len = MIN(len, maxlen); - - // copy the packet from the receive buffer - enc28j60ReadBuffer(len, buf); - - // Move the RX read pointer to the start of the next received packet - // This frees the memory we just read out - enc28j60Write(ERXRDPTL, (NextPacketPtr)); - enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8); - - // decrement the packet counter indicate we are done with this packet - enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); - - return len; +void enc28j60_send(uint8_t* buf, uint16_t len){ + + // Wait for any current transmission to finish + while(enc28j60_read_op(RCR, ECON1) & TXRTS){ + if(enc28j60_read(EIR) & TXERIF){ + enc28j60_write_op(BFS, ECON1, TXRST); + enc28j60_write_op(BFC, ECON1, TXRST); + } + } + + enc28j60_write(EWRPTL, (TXSTART_INIT & 0xFF)); + enc28j60_write(EWRPTH, (TXSTART_INIT >> 8)); + enc28j60_write(ETXNDL, ((TXSTART_INIT + len) & 0xFF)); + enc28j60_write(ETXNDH, ((TXSTART_INIT + len) >> 8)); + enc28j60_write_op(WBM, 0, 0x00); + enc28j60_write_buffer(buf, len); + enc28j60_write_op(BFS, ECON1, TXRTS); } diff --git a/firmware/octoclock/lib/init.c b/firmware/octoclock/lib/init.c index 827ccb376..8592aa091 100644 --- a/firmware/octoclock/lib/init.c +++ b/firmware/octoclock/lib/init.c @@ -71,7 +71,7 @@ void setup_atmel_io_ports(){ // /pd_cdcd, /sync_code, /ce need to be 1 (disabled) to start // all bits are outputs, except PA7 (gps_lock) and PA3 (MISO_CDCE) are inputs -PORTA = Bits_8(00110010); +PORTA = Bits_8(00100010); DDRA = 1< #include +#include #include #include @@ -34,12 +35,14 @@ #include #include +#include + #include "arp_cache.h" /*********************************************************************** * Constants + Globals **********************************************************************/ -static const size_t out_buff_size = 512; +static const size_t out_buff_size = ETH_BUF_SIZE; static const eth_mac_addr_t BCAST_MAC_ADDR = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; #define MAX_UDP_LISTENERS 10 @@ -139,7 +142,7 @@ send_pkt( //grab an out buffer and pointer //select the output buffer based on type of packet uint8_t *p; - p = buf_out; + p = eth_buf; size_t total_len = 0; //create a list of all buffers to copy @@ -149,7 +152,7 @@ send_pkt( //copy each buffer into the out buffer for (size_t i = 0; i < sizeof(buffs)/sizeof(buffs[0]); i++){ total_len += lens[i]; //use full length (not clipped) - size_t bytes_remaining = out_buff_size - (size_t)(p - (uint8_t*)buf_out); + size_t bytes_remaining = out_buff_size - (size_t)(p - (uint8_t*)eth_buf); if (lens[i] > bytes_remaining) lens[i] = bytes_remaining; memcpy(p, buffs[i], lens[i]); p += lens[i]; @@ -161,7 +164,7 @@ send_pkt( //For some reason, the ENC28J60 won't send the CRC //if you don't tell it to send another byte after //the given packet - enc28j60PacketSend(total_len+1, buf_out, 0, 0); + enc28j60_send(eth_buf, total_len); } static void @@ -333,15 +336,15 @@ handle_arp_packet(struct arp_eth_ipv4 *p, size_t size) void handle_eth_packet(size_t recv_len) { - eth_hdr_t *eth_hdr = (eth_hdr_t *)buf_in; + eth_hdr_t *eth_hdr = (eth_hdr_t *)eth_buf; uint16_t ethertype = htons(eth_hdr->ethertype); if (ethertype == ETHERTYPE_ARP){ - struct arp_eth_ipv4 *arp = (struct arp_eth_ipv4 *)(buf_in + sizeof(eth_hdr_t)); + struct arp_eth_ipv4 *arp = (struct arp_eth_ipv4 *)(eth_buf + sizeof(eth_hdr_t)); handle_arp_packet(arp, recv_len-ETH_HLEN); } else if (ethertype == ETHERTYPE_IPV4){ - struct ip_hdr *ip = (struct ip_hdr *)(buf_in + sizeof(eth_hdr_t)); + struct ip_hdr *ip = (struct ip_hdr *)(eth_buf + sizeof(eth_hdr_t)); if (_IPH_V(ip) != 4 || _IPH_HL(ip) != 5) // ignore pkts w/ bad version or options return; @@ -357,7 +360,7 @@ handle_eth_packet(size_t recv_len) bool is_my_ip = memcmp(&ip->dest, &htonl_local_ip_addr, sizeof(_local_ip_addr)) == 0; if (!is_bcast && !is_my_ip) return; - arp_cache_update(&ip->src, (eth_mac_addr_t *)(((char *)buf_in)+6)); + arp_cache_update(&ip->src, (eth_mac_addr_t *)(((char *)eth_buf)+6)); switch (_IPH_PROTO(ip)){ case IP_PROTO_UDP: @@ -381,7 +384,6 @@ handle_eth_packet(size_t recv_len) **********************************************************************/ static bool send_garp = false; -static bool sent_initial_garp = false; static uint32_t num_overflows = 0; // Six overflows is the closest overflow count to one minute. @@ -390,6 +392,7 @@ ISR(TIMER1_OVF_vect){ if(!(num_overflows % 6)) send_garp = true; } +// Send a GARP packet once per minute. static void send_gratuitous_arp(){ send_garp = false; @@ -415,18 +418,9 @@ send_gratuitous_arp(){ // Executed every loop void network_check(void){ - size_t recv_len = enc28j60PacketReceive(512, buf_in); + size_t recv_len = enc28j60_recv(eth_buf, ETH_BUF_SIZE); if(recv_len > 0) handle_eth_packet(recv_len); - /* - * Send a gratuitous ARP packet two seconds after Ethernet - * initialization. - */ - if(!sent_initial_garp && (num_overflows == 0 && TCNT1 > (TIMER1_ONE_SECOND*2))){ - sent_initial_garp = true; - send_garp = true; - } - if(send_garp) send_gratuitous_arp(); } @@ -435,9 +429,10 @@ void network_init(void){ * Read MAC address from EEPROM and initialize Ethernet driver. If EEPROM is blank, * use default MAC address instead. */ + eeprom_busy_wait(); if(eeprom_read_byte(0) == 0xFF){ _MAC_ADDR(_local_mac_addr.addr, 0x00,0x80,0x2F,0x11,0x22,0x33); - _local_ip_addr.addr = default_ip; + _local_ip_addr.addr = _IP(192,168,10,3); using_network_defaults = true; } else{ @@ -446,5 +441,8 @@ void network_init(void){ using_network_defaults = false; } - enc28j60Init((uint8_t*)&_local_mac_addr); + enc28j60_init((uint8_t*)&_local_mac_addr); + init_udp_listeners(); + + send_garp = true; } diff --git a/firmware/octoclock/lib/state.c b/firmware/octoclock/lib/state.c index 0dbcc6ece..26e1b783c 100644 --- a/firmware/octoclock/lib/state.c +++ b/firmware/octoclock/lib/state.c @@ -15,110 +15,80 @@ * along with this program. If not, see . */ -#include #include +#include #include #include #include #include -void led(LEDs which, int turn_it_on) { +// Global state variables +volatile bool g_ext_ref_present = false; +volatile bool g_gps_present = false; +volatile switch_pos_t g_switch_pos = PREFER_INTERNAL; +volatile ref_t g_ref = NO_REF; +void led(led_t which, bool on){ // selects the proper bit uint8_t LED = 0x20 << which; - if(turn_it_on) + if(on) PORTC |= LED; else PORTC &= ~LED; } -void LEDs_Off(void){ - led(Top,false); - led(Middle,false); - led(Bottom,false); +void leds_off(void){ + led(LED_TOP, false); + led(LED_MIDDLE, false); + led(LED_BOTTOM, false); } -void force_internal(void){ - led(Top,true); - led(Middle,false); - led(Bottom,true); +static void force_internal(void){ + led(LED_TOP, true); + led(LED_MIDDLE, false); + led(LED_BOTTOM, true); + // Tell ClkDist chip to use internal signals + cli(); setup_TI_CDCE18005(Primary_GPS); + sei(); - // Set PPS to Primary (1) n.b.: "1" in general means "Internal" for all - // such signals + // Set PPS to internal PORTA |= (1<sequence; - //If the firmware is incompatible, only respond to queries + // If the firmware is incompatible, only respond to queries if(pkt_in->code == OCTOCLOCK_QUERY_CMD){ pkt_out.code = OCTOCLOCK_QUERY_ACK; pkt_out.len = 0; @@ -50,44 +50,43 @@ void handle_udp_ctrl_packet( octoclock_fw_eeprom_t *eeprom_info = (octoclock_fw_eeprom_t*)pkt_out.data; - //Read values from EEPROM into packet + // Read values from EEPROM into packet + eeprom_busy_wait(); eeprom_read_block(eeprom_info, 0, sizeof(octoclock_fw_eeprom_t)); - //If EEPROM network fields are not fully populated, copy defaults + // If EEPROM network fields are not fully populated, copy defaults if(using_network_defaults){ _MAC_ADDR(eeprom_info->mac_addr, 0x00,0x80,0x2F,0x11,0x22,0x33); - eeprom_info->ip_addr = default_ip; - eeprom_info->dr_addr = default_dr; - eeprom_info->netmask = default_netmask; + eeprom_info->ip_addr = _IP(192,168,10,3); + eeprom_info->dr_addr = _IP(192,168,10,1); + eeprom_info->netmask = _IP(255,255,255,0); } - //Check if strings or revision is empty - if(eeprom_info->serial[0] == 0xFF) memset(eeprom_info->serial, 0, 10); - if(eeprom_info->name[0] == 0xFF) memset(eeprom_info->name, 0, 10); + // Check if strings or revision is empty if(eeprom_info->revision == 0xFF) eeprom_info->revision = 0; break; case BURN_EEPROM_CMD:{ - //Confirm length of data + // Confirm length of data if(pkt_in->len != sizeof(octoclock_fw_eeprom_t)){ pkt_out.code = BURN_EEPROM_FAILURE_ACK; break; } /* - * In all cases, a full octoclock_fw_eeprom_t is written to lower the overall - * number of writes due to this EEPROM's smaller amount of safe writes. * It is up to the host to make sure that the values that should be * preserved are present in the octoclock_fw_eeprom_t struct. */ const octoclock_fw_eeprom_t *eeprom_pkt = (octoclock_fw_eeprom_t*)pkt_in->data; pkt_out.len = 0; - //Write EEPROM data from packet + // Write EEPROM data from packet + eeprom_busy_wait(); eeprom_write_block(eeprom_pkt, 0, sizeof(octoclock_fw_eeprom_t)); - //Read back and compare to packet to confirm successful write + // Read back and compare to packet to confirm successful write uint8_t eeprom_contents[sizeof(octoclock_fw_eeprom_t)]; + eeprom_busy_wait(); eeprom_read_block(eeprom_contents, 0, sizeof(octoclock_fw_eeprom_t)); uint8_t n = memcmp(eeprom_contents, eeprom_pkt, sizeof(octoclock_fw_eeprom_t)); pkt_out.code = n ? BURN_EEPROM_FAILURE_ACK @@ -99,12 +98,12 @@ void handle_udp_ctrl_packet( pkt_out.code = SEND_STATE_ACK; pkt_out.len = sizeof(octoclock_state_t); - //Populate octoclock_state_t fields + // Populate octoclock_state_t fields octoclock_state_t *state = (octoclock_state_t*)pkt_out.data; - state->external_detected = global_ext_ref_is_present ? 1 : 0; - state->gps_detected = (PIND & _BV(DDD4)) ? 1 : 0; - state->which_ref = (uint8_t)which_ref(); - state->switch_pos = (uint8_t)get_switch_pos(); + state->external_detected = g_ext_ref_present ? 1 : 0; + state->gps_detected = g_gps_present ? 1 : 0; + state->which_ref = (uint8_t)g_ref; + state->switch_pos = (uint8_t)g_switch_pos; break; case RESET_CMD: diff --git a/firmware/octoclock/lib/usart.c b/firmware/octoclock/lib/usart.c index 3620ac5e9..a267e43c6 100644 --- a/firmware/octoclock/lib/usart.c +++ b/firmware/octoclock/lib/usart.c @@ -34,16 +34,8 @@ char usart_getc(void){ return UDR1; } -char usart_getc_noblock(void){ - return ((UCSR1A & (1 << RXC))) ? UDR1 : -1; -} - void usart_putc(char ch){ while((UCSR1A & (1 << UDRE1)) == 0); UDR1 = ch; } - -void usart_putc_nowait(char ch){ - if((UCSR1A & (1 << UDRE1)) != 0) UDR1 = ch; -} -- cgit v1.2.3