Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

v2.3 Migrated to v10.10.10 of sdfatlib. Moved to inline RX interrupt …

…and buffer. Improved the ability to receive a constant stream at 57600bps.

27334 bytes out of 30720.

Remember - we had to completely butcher HardwareSerial.cpp so a normal Arduino installation will not work.
C:\arduino-xxxx\hardware\arduino\cores\arduino\HardwareSerial.cpp

I removed the receive interrupt handler from HardwareSerial.cpp so that we can deal directly with USART_RX_vect in the main code. This allows us to return to the way OpenLog used to operate - by having one buffer split in half. Once one half fills, it is recorded to SD while the other half fills up. This dramatically decreases the time spent in function calls and SD recording, which leads to many fewer characters dropped.

The change log at the top of the main code got so large I've moved it to a version controlled "Changes.txt" file.

By making all these changes, I have broken many things. Ringp - I could use your help here. I apologize for stomping on so much of your work. I was not good enough to figure out how to re-link from the old function calls to the new sdfatlib setup.

Backspace is broken - ringp, I saw this fix in one of your commits, but looking at the code, I don't see how it is supposed to work. Either way, we still get 0x08 when trying to backspace.

Search for "//Error" in main pde
ls is not working fully
remove is not working
fileInfo is not working

New sdfatlib doesn't have SdFat.cpp so fileInfo doesn't work. These function calls are marked with //Error

I have chosen to dis-allow deprecated functions:
#define ALLOW_DEPRECATED_FUNCTIONS 0
This forced some trivial changes to the SD write and new file creation function calls. I believe we've successfully migrated to the new version of sdfatlib.

In the command_shell / read_line function : It may be better to pull directly from the UART buffer and use the RX interrupt. For now, we brute force it.

Because of all these changes, I need to re-test power consumption. For now, I'm confident it's low enough.

Testing with 512 buffer array size
1GB @ 57600 - dropped very little out of 3 tests
1GB @ 115200 - dropped very little out of 2 tests
8GB @ 57600 - Formatted using the sd formater (32k byte allocation size). Dropped nothing.
8GB @ 115200 - dropped very little, dropped none
16GB w/ Lots of files @ 57600 - Drops the first part of the file because of start up delay?
16GB w/ Lots of files @ 115200

1024 array size (and 800) does not run

Testing with 700 buffer array size
1GB @ 57600 - 110300 out of 111000 bytes, 110300/111000,
1GB @ 115200 - 111000/111000!, 109600/111000
8GB @ 57600 - 109000/111000, 111000/111000!,
8GB @ 115200 - 111000/111000!, 111000/111000!,
16GB w/ Lots of files @ 57600 - 85120/111000, 85120/111000
16GB w/ Lots of files @ 115200 - 56420 (but once it got going, log looks good). 56420.

I am seeing long delays on cards with lots of files. In the above tests, the 16GB test card is a good example. It has 2GB worth of random files in a sub directory. After OpenLog boots, goes to '12<'. After I send ~500 characters OpenLog freezes for a couple seconds, then returns to normal, very fast, operation. During that down time, I believe sdfatlib is searching for an open cluster. The odd thing is that after the cluster is established (after the initial down time) OpenLog performs excellently. I am hoping to create a faux file or pre-write and save to the file or some how get this allocation done before we report the '12<' indicating we are ready. That way, if a card does fill up, as long as the host system is checking for '<', it doesn't matter how long it takes sdfatlib to find the next free cluster.

You can see that we drop 700 bytes at a time. That's a bit odd - I'd expect to drop half or 350 at a time. What happens if we shrink the array size to say 256? To be expected, this is bad - way more instances of dropped characters.

Added blink for each test to the OpenLog_Test sketch so we can see as the test progresses.

http://www.sdcard.org/consumers/formatter/ is the site for SD card formatting. It looks like this program takes a guess at the correct block size. This could help a lot in the future.
  • Loading branch information...
commit 57890b6b133c20bbd88cd231bce966e183ba64fc 1 parent 56b6dd7
@nseidle nseidle authored
View
8 OpenLog_Test_Sketch/OpenLog_Test_Sketch.pde
@@ -50,7 +50,7 @@ void setup()
void loop()
{
- int testAmt = 4;
+ int testAmt = 10;
//At 9600, testAmt of 4 takes about 1 minute, 10 takes about 3 minutes
//At 57600, testAmt of 10 takes about 1 minute, 40 takes about 5 minutes
//testAmt of 10 will push 111,000 characters/bytes. With header and footer strings, total is 111,052
@@ -73,6 +73,12 @@ void loop()
Serial.println(":abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-!#");
//delay(50);
}
+
+ if(digitalRead(ledPin) == 0)
+ digitalWrite(ledPin, HIGH);
+ else
+ digitalWrite(ledPin, LOW);
+
}
}
View
611 OpenLog_v2/ArduinoPins.h
@@ -1,611 +0,0 @@
-// Map of Arduino pins to avr bit, ddr, port, pin
-// Credit Paul Stoffregen for idea
-#ifndef ArduinoPins_h
-#define ArduinoPins_h
-
-#define PIN_BITNUM(pin) (PIN ## pin ## _BITNUM)
-#define PIN_PORTREG(pin) (PIN ## pin ## _PORTREG)
-#define PIN_DDRREG(pin) (PIN ## pin ## _DDRREG)
-#define PIN_PINREG(pin) (PIN ## pin ## _PINREG)
-#ifndef _BV
-#define _BV(n) (1<<(n))
-#endif
-
-#if defined(__AVR_ATmega1280__)
-// Mega Arduino
-
-// Two Wire (aka I2C) ports
-#define SDA_PIN 20
-#define SCL_PIN 21
-
-// SPI port
-#define SS_PIN 53
-#define MOSI_PIN 51
-#define MISO_PIN 50
-#define SCK_PIN 52
-
-// bit number for all digital pins
-#define PIN0_BITNUM 0
-#define PIN1_BITNUM 1
-#define PIN2_BITNUM 4
-#define PIN3_BITNUM 5
-#define PIN4_BITNUM 5
-#define PIN5_BITNUM 3
-#define PIN6_BITNUM 3
-#define PIN7_BITNUM 4
-#define PIN8_BITNUM 5
-#define PIN9_BITNUM 6
-#define PIN10_BITNUM 4
-#define PIN11_BITNUM 5
-#define PIN12_BITNUM 6
-#define PIN13_BITNUM 7
-#define PIN14_BITNUM 1
-#define PIN15_BITNUM 0
-#define PIN16_BITNUM 1
-#define PIN17_BITNUM 0
-#define PIN18_BITNUM 3
-#define PIN19_BITNUM 2
-#define PIN20_BITNUM 1
-#define PIN21_BITNUM 0
-#define PIN22_BITNUM 0
-#define PIN23_BITNUM 1
-#define PIN24_BITNUM 2
-#define PIN25_BITNUM 3
-#define PIN26_BITNUM 4
-#define PIN27_BITNUM 5
-#define PIN28_BITNUM 6
-#define PIN29_BITNUM 7
-#define PIN30_BITNUM 7
-#define PIN31_BITNUM 6
-#define PIN32_BITNUM 5
-#define PIN33_BITNUM 4
-#define PIN34_BITNUM 3
-#define PIN35_BITNUM 2
-#define PIN36_BITNUM 1
-#define PIN37_BITNUM 0
-#define PIN38_BITNUM 7
-#define PIN39_BITNUM 2
-#define PIN40_BITNUM 1
-#define PIN41_BITNUM 0
-#define PIN42_BITNUM 7
-#define PIN43_BITNUM 6
-#define PIN44_BITNUM 5
-#define PIN45_BITNUM 4
-#define PIN46_BITNUM 3
-#define PIN47_BITNUM 2
-#define PIN48_BITNUM 1
-#define PIN49_BITNUM 0
-#define PIN50_BITNUM 3
-#define PIN51_BITNUM 2
-#define PIN52_BITNUM 1
-#define PIN53_BITNUM 0
-#define PIN54_BITNUM 0
-#define PIN55_BITNUM 1
-#define PIN56_BITNUM 2
-#define PIN57_BITNUM 3
-#define PIN58_BITNUM 4
-#define PIN59_BITNUM 5
-#define PIN60_BITNUM 6
-#define PIN61_BITNUM 7
-#define PIN62_BITNUM 0
-#define PIN63_BITNUM 1
-#define PIN64_BITNUM 2
-#define PIN65_BITNUM 3
-#define PIN66_BITNUM 4
-#define PIN67_BITNUM 5
-#define PIN68_BITNUM 6
-#define PIN69_BITNUM 7
-
-// output register for digital pins
-#define PIN0_PORTREG PORTE
-#define PIN1_PORTREG PORTE
-#define PIN2_PORTREG PORTE
-#define PIN3_PORTREG PORTE
-#define PIN4_PORTREG PORTG
-#define PIN5_PORTREG PORTE
-#define PIN6_PORTREG PORTH
-#define PIN7_PORTREG PORTH
-#define PIN8_PORTREG PORTH
-#define PIN9_PORTREG PORTH
-#define PIN10_PORTREG PORTB
-#define PIN11_PORTREG PORTB
-#define PIN12_PORTREG PORTB
-#define PIN13_PORTREG PORTB
-#define PIN14_PORTREG PORTJ
-#define PIN15_PORTREG PORTJ
-#define PIN16_PORTREG PORTH
-#define PIN17_PORTREG PORTH
-#define PIN18_PORTREG PORTD
-#define PIN19_PORTREG PORTD
-#define PIN20_PORTREG PORTD
-#define PIN21_PORTREG PORTD
-#define PIN22_PORTREG PORTA
-#define PIN23_PORTREG PORTA
-#define PIN24_PORTREG PORTA
-#define PIN25_PORTREG PORTA
-#define PIN26_PORTREG PORTA
-#define PIN27_PORTREG PORTA
-#define PIN28_PORTREG PORTA
-#define PIN29_PORTREG PORTA
-#define PIN30_PORTREG PORTC
-#define PIN31_PORTREG PORTC
-#define PIN32_PORTREG PORTC
-#define PIN33_PORTREG PORTC
-#define PIN34_PORTREG PORTC
-#define PIN35_PORTREG PORTC
-#define PIN36_PORTREG PORTC
-#define PIN37_PORTREG PORTC
-#define PIN38_PORTREG PORTD
-#define PIN39_PORTREG PORTG
-#define PIN40_PORTREG PORTG
-#define PIN41_PORTREG PORTG
-#define PIN42_PORTREG PORTL
-#define PIN43_PORTREG PORTL
-#define PIN44_PORTREG PORTL
-#define PIN45_PORTREG PORTL
-#define PIN46_PORTREG PORTL
-#define PIN47_PORTREG PORTL
-#define PIN48_PORTREG PORTL
-#define PIN49_PORTREG PORTL
-#define PIN50_PORTREG PORTB
-#define PIN51_PORTREG PORTB
-#define PIN52_PORTREG PORTB
-#define PIN53_PORTREG PORTB
-#define PIN54_PORTREG PORTF
-#define PIN55_PORTREG PORTF
-#define PIN56_PORTREG PORTF
-#define PIN57_PORTREG PORTF
-#define PIN58_PORTREG PORTF
-#define PIN59_PORTREG PORTF
-#define PIN60_PORTREG PORTF
-#define PIN61_PORTREG PORTF
-#define PIN62_PORTREG PORTK
-#define PIN63_PORTREG PORTK
-#define PIN64_PORTREG PORTK
-#define PIN65_PORTREG PORTK
-#define PIN66_PORTREG PORTK
-#define PIN67_PORTREG PORTK
-#define PIN68_PORTREG PORTK
-#define PIN69_PORTREG PORTK
-
-// direction control register for digital pins
-#define PIN0_DDRREG DDRE
-#define PIN1_DDRREG DDRE
-#define PIN2_DDRREG DDRE
-#define PIN3_DDRREG DDRE
-#define PIN4_DDRREG DDRG
-#define PIN5_DDRREG DDRE
-#define PIN6_DDRREG DDRH
-#define PIN7_DDRREG DDRH
-#define PIN8_DDRREG DDRH
-#define PIN9_DDRREG DDRH
-#define PIN10_DDRREG DDRB
-#define PIN11_DDRREG DDRB
-#define PIN12_DDRREG DDRB
-#define PIN13_DDRREG DDRB
-#define PIN14_DDRREG DDRJ
-#define PIN15_DDRREG DDRJ
-#define PIN16_DDRREG DDRH
-#define PIN17_DDRREG DDRH
-#define PIN18_DDRREG DDRD
-#define PIN19_DDRREG DDRD
-#define PIN20_DDRREG DDRD
-#define PIN21_DDRREG DDRD
-#define PIN22_DDRREG DDRA
-#define PIN23_DDRREG DDRA
-#define PIN24_DDRREG DDRA
-#define PIN25_DDRREG DDRA
-#define PIN26_DDRREG DDRA
-#define PIN27_DDRREG DDRA
-#define PIN28_DDRREG DDRA
-#define PIN29_DDRREG DDRA
-#define PIN30_DDRREG DDRC
-#define PIN31_DDRREG DDRC
-#define PIN32_DDRREG DDRC
-#define PIN33_DDRREG DDRC
-#define PIN34_DDRREG DDRC
-#define PIN35_DDRREG DDRC
-#define PIN36_DDRREG DDRC
-#define PIN37_DDRREG DDRC
-#define PIN38_DDRREG DDRD
-#define PIN39_DDRREG DDRG
-#define PIN40_DDRREG DDRG
-#define PIN41_DDRREG DDRG
-#define PIN42_DDRREG DDRL
-#define PIN43_DDRREG DDRL
-#define PIN44_DDRREG DDRL
-#define PIN45_DDRREG DDRL
-#define PIN46_DDRREG DDRL
-#define PIN47_DDRREG DDRL
-#define PIN48_DDRREG DDRL
-#define PIN49_DDRREG DDRL
-#define PIN50_DDRREG DDRB
-#define PIN51_DDRREG DDRB
-#define PIN52_DDRREG DDRB
-#define PIN53_DDRREG DDRB
-#define PIN54_DDRREG DDRF
-#define PIN55_DDRREG DDRF
-#define PIN56_DDRREG DDRF
-#define PIN57_DDRREG DDRF
-#define PIN58_DDRREG DDRF
-#define PIN59_DDRREG DDRF
-#define PIN60_DDRREG DDRF
-#define PIN61_DDRREG DDRF
-#define PIN62_DDRREG DDRK
-#define PIN63_DDRREG DDRK
-#define PIN64_DDRREG DDRK
-#define PIN65_DDRREG DDRK
-#define PIN66_DDRREG DDRK
-#define PIN67_DDRREG DDRK
-#define PIN68_DDRREG DDRK
-#define PIN69_DDRREG DDRK
-
-// input register for digital pins
-#define PIN0_PINREG PINE
-#define PIN1_PINREG PINE
-#define PIN2_PINREG PINE
-#define PIN3_PINREG PINE
-#define PIN4_PINREG PING
-#define PIN5_PINREG PINE
-#define PIN6_PINREG PINH
-#define PIN7_PINREG PINH
-#define PIN8_PINREG PINH
-#define PIN9_PINREG PINH
-#define PIN10_PINREG PINB
-#define PIN11_PINREG PINB
-#define PIN12_PINREG PINB
-#define PIN13_PINREG PINB
-#define PIN14_PINREG PINJ
-#define PIN15_PINREG PINJ
-#define PIN16_PINREG PINH
-#define PIN17_PINREG PINH
-#define PIN18_PINREG PIND
-#define PIN19_PINREG PIND
-#define PIN20_PINREG PIND
-#define PIN21_PINREG PIND
-#define PIN22_PINREG PINA
-#define PIN23_PINREG PINA
-#define PIN24_PINREG PINA
-#define PIN25_PINREG PINA
-#define PIN26_PINREG PINA
-#define PIN27_PINREG PINA
-#define PIN28_PINREG PINA
-#define PIN29_PINREG PINA
-#define PIN30_PINREG PINC
-#define PIN31_PINREG PINC
-#define PIN32_PINREG PINC
-#define PIN33_PINREG PINC
-#define PIN34_PINREG PINC
-#define PIN35_PINREG PINC
-#define PIN36_PINREG PINC
-#define PIN37_PINREG PINC
-#define PIN38_PINREG PIND
-#define PIN39_PINREG PING
-#define PIN40_PINREG PING
-#define PIN41_PINREG PING
-#define PIN42_PINREG PINL
-#define PIN43_PINREG PINL
-#define PIN44_PINREG PINL
-#define PIN45_PINREG PINL
-#define PIN46_PINREG PINL
-#define PIN47_PINREG PINL
-#define PIN48_PINREG PINL
-#define PIN49_PINREG PINL
-#define PIN50_PINREG PINB
-#define PIN51_PINREG PINB
-#define PIN52_PINREG PINB
-#define PIN53_PINREG PINB
-#define PIN54_PINREG PINF
-#define PIN55_PINREG PINF
-#define PIN56_PINREG PINF
-#define PIN57_PINREG PINF
-#define PIN58_PINREG PINF
-#define PIN59_PINREG PINF
-#define PIN60_PINREG PINF
-#define PIN61_PINREG PINF
-#define PIN62_PINREG PINK
-#define PIN63_PINREG PINK
-#define PIN64_PINREG PINK
-#define PIN65_PINREG PINK
-#define PIN66_PINREG PINK
-#define PIN67_PINREG PINK
-#define PIN68_PINREG PINK
-#define PIN69_PINREG PINK
-
-#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
-// ATMEL ATMEGA644P / SANGUINO
-//
-// +---\/---+
-// INT0 (D 0) PB0 1| |40 PA0 (AI 0 / D31)
-// INT1 (D 1) PB1 2| |39 PA1 (AI 1 / D30)
-// INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29)
-// PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28)
-// PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27)
-// MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26)
-// MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25)
-// SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24)
-// RST 9| |32 AREF
-// VCC 10| |31 GND
-// GND 11| |30 AVCC
-// XTAL2 12| |29 PC7 (D 23)
-// XTAL1 13| |28 PC6 (D 22)
-// RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI
-// TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO
-// RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS
-// TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK
-// PWM (D 12) PD4 18| |23 PC1 (D 17) SDA
-// PWM (D 13) PD5 19| |22 PC0 (D 16) SCL
-// PWM (D 14) PD6 20| |21 PD7 (D 15) PWM
-// +--------+
-//
-
-#error Sanguino not tested
-
-// Two Wire (aka I2C) ports
-#define SDA_PIN 17
-#define SCL_PIN 18
-
-// SPI port
-#define SS_PIN 4
-#define MOSI_PIN 5
-#define MISO_PIN 6
-#define SCK_PIN 7
-
-// bit number for all digital pins
-#define PIN0_BITNUM 0
-#define PIN1_BITNUM 1
-#define PIN2_BITNUM 2
-#define PIN3_BITNUM 3
-#define PIN4_BITNUM 4
-#define PIN5_BITNUM 5
-#define PIN6_BITNUM 6
-#define PIN7_BITNUM 7
-#define PIN8_BITNUM 0
-#define PIN9_BITNUM 1
-#define PIN10_BITNUM 2
-#define PIN11_BITNUM 3
-#define PIN12_BITNUM 4
-#define PIN13_BITNUM 5
-#define PIN14_BITNUM 6
-#define PIN15_BITNUM 7
-#define PIN16_BITNUM 0
-#define PIN17_BITNUM 1
-#define PIN18_BITNUM 2
-#define PIN19_BITNUM 3
-#define PIN20_BITNUM 4
-#define PIN21_BITNUM 5
-#define PIN22_BITNUM 6
-#define PIN23_BITNUM 7
-#define PIN24_BITNUM 7
-#define PIN25_BITNUM 6
-#define PIN26_BITNUM 5
-#define PIN27_BITNUM 4
-#define PIN28_BITNUM 3
-#define PIN29_BITNUM 2
-#define PIN30_BITNUM 1
-#define PIN31_BITNUM0
-
-// output register for digital pins
-#define PIN0_PORTREG PORTB
-#define PIN1_PORTREG PORTB
-#define PIN2_PORTREG PORTB
-#define PIN3_PORTREG PORTB
-#define PIN4_PORTREG PORTB
-#define PIN5_PORTREG PORTB
-#define PIN6_PORTREG PORTB
-#define PIN7_PORTREG PORTB
-#define PIN8_PORTREG PORTD
-#define PIN9_PORTREG PORTD
-#define PIN10_PORTREG PORTD
-#define PIN11_PORTREG PORTD
-#define PIN12_PORTREG PORTD
-#define PIN13_PORTREG PORTD
-#define PIN14_PORTREG PORTD
-#define PIN15_PORTREG PORTD
-#define PIN16_PORTREG PORTC
-#define PIN17_PORTREG PORTC
-#define PIN18_PORTREG PORTC
-#define PIN19_PORTREG PORTC
-#define PIN20_PORTREG PORTC
-#define PIN21_PORTREG PORTC
-#define PIN22_PORTREG PORTC
-#define PIN23_PORTREG PORTC
-#define PIN24_PORTREG PORTA
-#define PIN25_PORTREG PORTA
-#define PIN26_PORTREG PORTA
-#define PIN27_PORTREG PORTA
-#define PIN28_PORTREG PORTA
-#define PIN29_PORTREG PORTA
-#define PIN30_PORTREG PORTA
-#define PIN31_PORTREG PORTA
-
-
-// direction control register for digital pins
-#define PIN0_DDRREG DDRB
-#define PIN1_DDRREG DDRB
-#define PIN2_DDRREG DDRB
-#define PIN3_DDRREG DDRB
-#define PIN4_DDRREG DDRB
-#define PIN5_DDRREG DDRB
-#define PIN6_DDRREG DDRB
-#define PIN7_DDRREG DDRB
-#define PIN8_DDRREG DDRD
-#define PIN9_DDRREG DDRD
-#define PIN10_DDRREG DDRD
-#define PIN11_DDRREG DDRD
-#define PIN12_DDRREG DDRD
-#define PIN13_DDRREG DDRD
-#define PIN14_DDRREG DDRD
-#define PIN15_DDRREG DDRD
-#define PIN16_DDRREG DDRC
-#define PIN17_DDRREG DDRC
-#define PIN18_DDRREG DDRC
-#define PIN19_DDRREG DDRC
-#define PIN20_DDRREG DDRC
-#define PIN21_DDRREG DDRC
-#define PIN22_DDRREG DDRC
-#define PIN23_DDRREG DDRC
-#define PIN24_DDRREG DDRA
-#define PIN25_DDRREG DDRA
-#define PIN26_DDRREG DDRA
-#define PIN27_DDRREG DDRA
-#define PIN28_DDRREG DDRA
-#define PIN29_DDRREG DDRA
-#define PIN30_DDRREG DDRA
-#define PIN31_DDRREG DDRA
-
-
-// input register for digital pins
-#define PIN0_PINREG PINB
-#define PIN1_PINREG PINB
-#define PIN2_PINREG PINB
-#define PIN3_PINREG PINB
-#define PIN4_PINREG PINB
-#define PIN5_PINREG PINB
-#define PIN6_PINREG PINB
-#define PIN7_PINREG PINB
-#define PIN8_PINREG PIND
-#define PIN9_PINREG PIND
-#define PIN10_PINREG PIND
-#define PIN11_PINREG PIND
-#define PIN12_PINREG PIND
-#define PIN13_PINREG PIND
-#define PIN14_PINREG PIND
-#define PIN15_PINREG PIND
-#define PIN16_PINREG PINC
-#define PIN17_PINREG PINC
-#define PIN18_PINREG PINC
-#define PIN19_PINREG PINC
-#define PIN20_PINREG PINC
-#define PIN21_PINREG PINC
-#define PIN22_PINREG PINC
-#define PIN23_PINREG PINC
-#define PIN24_PINREG PINA
-#define PIN25_PINREG PINA
-#define PIN26_PINREG PINA
-#define PIN27_PINREG PINA
-#define PIN28_PINREG PINA
-#define PIN29_PINREG PINA
-#define PIN30_PINREG PINA
-#define PIN31_PINREG PINA
-
-
-#else // defined(__AVR_ATmega1280__)
-// 168 and 328 Arduinos
-//
-// +-\/-+
-// PC6 1| |28 PC5 (AI 5 D 19) SCL
-// (D 0) PD0 2| |27 PC4 (AI 4 D 18) SDA
-// (D 1) PD1 3| |26 PC3 (AI 3 D 17)
-// (D 2) PD2 4| |25 PC2 (AI 2 D 16)
-// PWM+ (D 3) PD3 5| |24 PC1 (AI 1 D 15)
-// (D 4) PD4 6| |23 PC0 (AI 0 D 14)
-// VCC 7| |22 GND
-// GND 8| |21 AREF
-// PB6 9| |20 AVCC
-// PB7 10| |19 PB5 (D 13) SCK
-// PWM+ (D 5) PD5 11| |18 PB4 (D 12) MISO
-// PWM+ (D 6) PD6 12| |17 PB3 (D 11) MOSI PWM
-// (D 7) PD7 13| |16 PB2 (D 10) SS PWM
-// (D 8) PB0 14| |15 PB1 (D 9) PWM
-// +----+
-//
-// Two Wire (aka I2C) ports
-#define SDA_PIN 18
-#define SCL_PIN 19
-
-// SPI port
-#define SS_PIN 10
-#define MOSI_PIN 11
-#define MISO_PIN 12
-#define SCK_PIN 13
-
-// bit number for digital pins
-#define PIN0_BITNUM 0
-#define PIN1_BITNUM 1
-#define PIN2_BITNUM 2
-#define PIN3_BITNUM 3
-#define PIN4_BITNUM 4
-#define PIN5_BITNUM 5
-#define PIN6_BITNUM 6
-#define PIN7_BITNUM 7
-#define PIN8_BITNUM 0
-#define PIN9_BITNUM 1
-#define PIN10_BITNUM 2
-#define PIN11_BITNUM 3
-#define PIN12_BITNUM 4
-#define PIN13_BITNUM 5
-#define PIN14_BITNUM 0
-#define PIN15_BITNUM 1
-#define PIN16_BITNUM 2
-#define PIN17_BITNUM 3
-#define PIN18_BITNUM 4
-#define PIN19_BITNUM 5
-
-// output register for all pins
-#define PIN0_PORTREG PORTD
-#define PIN1_PORTREG PORTD
-#define PIN2_PORTREG PORTD
-#define PIN3_PORTREG PORTD
-#define PIN4_PORTREG PORTD
-#define PIN5_PORTREG PORTD
-#define PIN6_PORTREG PORTD
-#define PIN7_PORTREG PORTD
-#define PIN8_PORTREG PORTB
-#define PIN9_PORTREG PORTB
-#define PIN10_PORTREG PORTB
-#define PIN11_PORTREG PORTB
-#define PIN12_PORTREG PORTB
-#define PIN13_PORTREG PORTB
-#define PIN14_PORTREG PORTC
-#define PIN15_PORTREG PORTC
-#define PIN16_PORTREG PORTC
-#define PIN17_PORTREG PORTC
-#define PIN18_PORTREG PORTC
-#define PIN19_PORTREG PORTC
-
-// direction control register for digital pins
-#define PIN0_DDRREG DDRD
-#define PIN1_DDRREG DDRD
-#define PIN2_DDRREG DDRD
-#define PIN3_DDRREG DDRD
-#define PIN4_DDRREG DDRD
-#define PIN5_DDRREG DDRD
-#define PIN6_DDRREG DDRD
-#define PIN7_DDRREG DDRD
-#define PIN8_DDRREG DDRB
-#define PIN9_DDRREG DDRB
-#define PIN10_DDRREG DDRB
-#define PIN11_DDRREG DDRB
-#define PIN12_DDRREG DDRB
-#define PIN13_DDRREG DDRB
-#define PIN14_DDRREG DDRC
-#define PIN15_DDRREG DDRC
-#define PIN16_DDRREG DDRC
-#define PIN17_DDRREG DDRC
-#define PIN18_DDRREG DDRC
-#define PIN19_DDRREG DDRC
-
-// input register for digital pins
-#define PIN0_PINREG PIND
-#define PIN1_PINREG PIND
-#define PIN2_PINREG PIND
-#define PIN3_PINREG PIND
-#define PIN4_PINREG PIND
-#define PIN5_PINREG PIND
-#define PIN6_PINREG PIND
-#define PIN7_PINREG PIND
-#define PIN8_PINREG PINB
-#define PIN9_PINREG PINB
-#define PIN10_PINREG PINB
-#define PIN11_PINREG PINB
-#define PIN12_PINREG PINB
-#define PIN13_PINREG PINB
-#define PIN14_PINREG PINC
-#define PIN15_PINREG PINC
-#define PIN16_PINREG PINC
-#define PIN17_PINREG PINC
-#define PIN18_PINREG PINC
-#define PIN19_PINREG PINC
-#endif // defined(__AVR_ATmega1280__)
-#endif // ArduinoPins_h
View
352 OpenLog_v2/Changes.txt
@@ -0,0 +1,352 @@
+ 12-3-09
+ Copyright SparkFun Electronics� 2010
+ Nathan Seidle
+ spark at sparkfun.com
+
+ OpenLog is a simple serial logger based on the ATmega328 running at 16MHz. The ATmega328
+ should be able to talk to high capacity (larger than 2GB) SD cards. The whole purpose of this
+ logger was to create a logger that just powered up and worked. OpenLog ships with standard
+ 57600bps serial bootloader running at 16MHz so you can load new firmware with a simple serial
+ connection. This makes it compatible with Arduino if needed.
+
+ OpenLog runs at 9600bps by default. This is configurable to 2400, 9600, 57600, and 115200bps. We recommend
+ you attach a serial connection to reconfigure the unit to work at a different serial speed, but you
+ should be able to do it in software.
+
+ Type '?' to get a list of supported commands.
+
+ During power up, you will see '12<'. '1' indicates the serial connection is established. '2' indicates
+ the SD card has been successfully initialized. '<' indicates OpenLog is ready to receive serial characters.
+
+ Recording constant 115200bps datastreams are supported. Throw it everything you've got!
+
+ 'cd ..' is a bit weird. Normally it's 'cd..' but to change to a lower dir, use 'cd ..'
+
+ Currently, the firmware supports creating a new file or directory up to 16 characters including the
+ '.' and extension. "123456789012.txt" is the longest name. Any longer and the module will re-initialize
+ as if there was a variable sizeof error.
+
+ Capital letters, white space, and other characters are supported ("Hi there#$_.txt").
+
+ Type 'set' to enter baud rate configuration menu. Select the baud rate and press enter. You will then
+ see a message 'Going to 9600bps...' or some such message. You will need to power down OpenLog, change
+ your system UART settings to match the new OpenLog baud rate and then power OpenLog back up.
+
+ If you get OpenLog stuck into an unknown baudrate, there is a safety mechanism built-in. Tie the RX pin
+ to ground and power up OpenLog. You should see the LEDs blink back and forth for 2 seconds, then blink
+ in unison. Now power down OpenLog and remove the RX/GND jumper. OpenLog is now reset to 9600bps.
+
+ Please note: The preloaded STK500 serial bootloader is 2k, and begins at 0x7800 (30,720). If the code is
+ larger than 30,719 bytes, you will get verification errors during serial bootloading.
+
+ SD vs HCSD configuration is found in sd_raw_config.h - Currently only 512MB, 1GB, 2GB, and some
+ 4GB cards work (not yet compatible with HCSD cards).
+
+ STAT1 LED is sitting on PD5 (Arduino D5) - toggles when character is received
+ STAT2 LED is sitting on PB5 (Arduino D13) - toggles when SPI writes happen
+
+ LED Flashing errors @ 2Hz:
+ No SD card - 3 blinks
+ Baud rate change (requires power cycle) - 4 blinks
+
+ During an append, OpenLog will buffer 512 characters at a time. That means that if the system loses power
+ while reading in characters, you may loose up to, but no more than, 511 characters. This is important for low
+ power systems where you may not know when the battery or power will die. OpenLog should record each buffer as
+ it receives each 512 byte chunk. The only way to exit an append is with Ctrl+z (ASCII 26).
+
+ 8mA idle
+ 18mA actively writing
+
+ Input voltage on VCC can be 3.3 to 12V. Input voltage on RX-I pin must not exceed 6V. Output voltage on
+ TX-O pin will not be greater than 3.3V. This may cause problems with some systems - for example if your
+ attached microcontroller requires 4V minimum for serial communication (this is rare).
+
+
+ v1.1
+ Adding better defines for EEPROM settings
+ Adding new log and sequential log functions.
+
+ Code is acting very weird with what looks to be stack crashes. I can get around this by turning the optimizer off ('0').
+ Found an error : EEPROM functions fail when optimizer is set to '0' or '1'.
+ sd-reader_config.h contains flag for USE_DYNAMIC_MEMORY
+
+ Looks like tweaking the optimization higher causes the asm("nop"); to fail inside the append_file routine. Changing this to
+ delay_us(1); works.
+
+ I have a sneaking suspicion that I was having buffer overrun problems when defining the input_buffer at 1024 bytes. The
+ ATmega328 should have enough RAM (2K) but weird reset errors were occuring. With the buffer at 512bytes, append_file runs
+ just fine and is able to log at 115200 at a constant data rate.
+
+ Added file called 'lots-o-text.txt' to version control. This text contains easy to scan text to be used for full data
+ rate checking and testing.
+
+
+ v1.2
+ ringp added:
+ Adding support for splitting command line parameters into arguments
+ Adding support for reading files sequencially
+ read <filename> <start> <length>
+ New log now for sequencial log functions supports 0-65535 files
+ Adding support for wildcard listing or deletion of files
+ ls <wildcard search>
+ rm <wildcard delete>
+
+ Really great additions. Thanks ringp!
+
+ Nate added error testing within newlog()
+ Checks to see if we have 65534 logs. If so, error out to command prompt with "!Too many logs:1"
+
+
+ v1.3
+ Added sd_raw_sync() inside append_file. I believe this was why tz1's addition of the timeout buffer update feature
+ was not working. Auto buffer update now working. So if you don't send anything to OpenLog for 5 seconds,
+ the buffer will automatically record/update.
+
+ Need to create 'Testing' page to outline the battery of tests we need to throw at any OpenLog after a firmware
+ submission and update is complete.
+
+ Testing
+ create 40,000 logs
+
+ Record at full speed:
+ Run at full 115200, load lotsoftext.txt and verify no characters are dropped.
+
+ Detect too many logs:
+ Create new log at 65533 (do this by editing 'zero' function to set EEPROM to 0xFF and oxFD)
+ and power cycle. Verify unit starts new log. Power cycle and verify unit errors out and drops to command prompt.
+
+ Record buffer after timeout:
+ Create new log. Type 20 characters and wait 5 seconds. Unit should auto-record buffer. Power down unit.
+ Power up unit and verify LOG has 20 characters recorded.
+
+
+ v1.4
+ Added exit options to the two menus (set and baud)
+ Also added display of current settin to two menus (Ex: "Baud currently: 57600bps")
+
+ Added '!' infront of 'error opening'. This pops up if there is an error while trying to append
+ to a freshly created new log (ex: LOG00548.txt is created, then errors out because it cannot append).
+ '!' was added so that user can parse against it.
+
+ Replicated logging errors at 57600 using 5V Arduino
+ Unit would systematically glitch during logging of 111054 bytes
+
+ Increasing buffer to 1000 characters caused URU error.
+ URU: Unit Resets Unexpectedly
+
+ To recreate URU error. Type "append ". Include the space. If you get "!error opening", then things are
+ fine. If you get "!error opening#" where # is a weird character, then type 'ls' and the unit will
+ unexpectedly reset (URU error). I believe this is attributed to a memory overrun somewhere in the
+ FAT system.
+
+ Changed buffer size to 900 and declared the character buffer as volatile
+ #define BUFF_LEN 900
+ volatile char input_buffer[BUFF_LEN];
+
+ This increase to the buffer allows for clean logging of 444055 bytes with no URU errors.
+
+ Experimenting with Scott's SD cards (customer gave cards on loan for recreating logging errors):
+ Card with single ~740mb file produces errors when trying to open/append to new log.
+ Card with less stuff on it logs full 444055 bytes correctly.
+
+
+ v1.5
+ Added 4800bps and 19200bps support
+
+ Added power saving features. Current consumption at 5V is now:
+ In default append mode:
+ 6.6/5.5mA while receiving characters (LED On/Off)
+ 2.1mA during idle
+ In command mode: 3.2/2.1mA (LED On/Off)
+
+ So if you're actively throwing characters at the logger, it will be ~6mA. If you send the logger
+ characters then delay 5-10 seconds, current will be ~2.5mA. (Unit records the characters in the buffer
+ and goes into idle more if no characters are received after 5 seconds)
+
+ These power savings required some significant changes to uart.c / uart_getc()
+
+
+ v1.51 check_emergency_reset, default break character is ctrl+z 3 times, example Arduino sketch
+
+ Added function from mungewell - check_emergency_reset. This has improved testing of the RX pin.
+ There was potential to get a false baud reset. There is still a chance but it's now much less likely.
+
+ If OpenLog is attached to a Arduino, during bootloading of the Arduino, ctrl+z will most likely be sent
+ to the Arduino from the computer. This character will cause OpenLog to drop to command mode - probably
+ not what we want. So I added user selectable character (ctrl+x or '$' for example) and I added
+ user selectable number of escape characters to look for in a row (example is 1 or 2 or 3, '$$$' is a
+ common escape sequence). The default is now ctrl+z sent 3 times in a row.
+
+ Added an example Arduino sketch (from ScottH) to GitHub so that people can easily see how to send characters to
+ OpenLog. Not much to it, but it does allow us to test large amounts of text thrown at OpenLog
+ at 57600bps.
+
+
+ v1.6 Adding config file.
+
+ What happens if I reset the system by pulling RX low, but the config file has corrupt values in it?
+
+ If config file has corrupt values in it, system will default to known values 9600/ctrl+z/3/newlog
+
+ If config file is empty, system resets to known values
+
+ After some massive testing, and lots of code to check for illegal states, it looks to be pretty stable.
+ The only problem is that we're running out of RAM. The buffer had to be decreased from 900 bytes
+ to 700 bytes to facilitate all the config file checking. Testing at 57600bps, unit runs very well
+ over 40kb test file on straight RS232 connection. That's pretty good. Testing at 115200 on straight
+ connection, unit will drop a buffer every once and a while. Not great, but not much we can do if the
+ SD card times out for ~150ms while it's writing.
+ 8 bits to the byte plus a start/stop bit = 10 bits per byte
+
+ @ 9600bps = 960 bytes per second. Buffer will last for 729ms
+ @ 57600bps = 5760 bytes per second. Buffer will last for 121ms
+ @ 115200bps = 11520 bytes per second. Buffer will last for 60.7ms
+
+ So if the SD card pauses for more than 60ms, 115200 will have lost data, sometimes. All other baud rates
+ should be covered for the most part.
+
+ SD cards with larges amounts of data will have increased pause rates. Always use a clean card where possible.
+
+
+ v1.61 Small PCB change. Fixed version # in help menu.
+
+ Fixed the firmware version in the help menu to v1.61.
+
+ Updated Eagle files to Eagle v5.9. Fixed weird airwire. Changed D1 LED from Green to Blue.
+ Will only affect new production after 4-28-10.
+
+ Closed some tickets and wrote some more example Arduino code:
+ http://forum.sparkfun.com/viewtopic.php?t=21438
+
+
+ v2.0 - 25986 bytes out of 30720
+ Welcome to version 2! We've moved from Roland Riegel's FAT library to Bill Greiman's sdfatlib. OpenLog now works with SD cards
+ up to 16GB (that is the current largest microSD card we can get our hands on). OpenLog automatically detects and works with FAT16/FAT32
+ file systems. It also automatically works with normal SD cards as well as SDHC cards.
+
+ Almost all the previous commands have been ported from v1 to v2. The current commands that do not work:
+ cd.. - does not work. You can change to an upper directory, but you cannot navigate back down the tree.
+ cat - this command was depricated. HEX printing is now done with the 'read' command. We've added a 5th argument to select between ASCII and HEX printing.
+ Wild cards do not yet work. So rm and ls do not have wild cards enabled - yet. Help us out!
+
+ Porting OpenLog to work directly under Arduino to work with sdfatlib (http://code.google.com/p/sdfatlib/) by Bill Greiman.
+
+ sdfatlib intrinsically supports FAT16, FAT32 as well as SD and HCSD cards. In a word, it's amazing.
+
+ Needs to be done:
+ Done - Get config file reading/loading working
+ Document config file in wiki: if no config file is found, current system settings are used. If config is found, system switches to settings found in file. If system settings are changed, then config file is changed and system uses new settings immediately.
+ Done - We don't want to constantly record a new config file on each power on. Only record when there is a change.
+ Get cd.. working
+ Seperate OpenLog_v2 into multiple files
+ Re-test too many log files created in the newlog setting - 65535. Potentially create thousands of files and see how sdfatlib handles it.
+ Done - Test sequential logging.
+ Get wild card support working for ls and rm
+ Get backspace working
+ Test rm with directories, and directory wildcards? Maybe not.
+ Get power save working
+ Test compile on a computer that doesn't have WinAVR
+
+ Test commands:
+ new - works, also in sub dirs
+ append - works, also in sub dirs
+ rm - works, but does not yet support wild cards.
+ md - works, also in sub dirs
+ cd - you can change up to a sub-directory, but you cannot navigate back down the tree. The current work around is to type 'init'. This will re-init the card and set the directory back to root.
+ ls - works pretty well but does not yet support wild cards. Shows directories, files, and file sizes. Would be cool if it listed dirs first.
+ read - works well. Tested 0, 1, 2, 3, 4, and 5 arguments (included and left off). Fails gracefully. Now prints in HEX as well!
+ size - works well
+ disk - works well, prints more information than ever before!
+ init - works well
+ sync - works, but not really tested
+ cat - I've decided to drop this command. You can now print in hex using the read command and using a 5th argument as '1' for ASCII (default) and '2' for HEX.
+
+ set - works well
+ baud - works well
+
+
+ v2.1 - Power save not working. Fixed issue 35. Dropping characters at 57600bps.
+ 26058 bytes out of 30720
+ Fixed a bug found by Salient (Issue 35). User settings where declared at chars which allowed them to be signed. If a user went from old firmware, to v2,
+ the safety checks would fail because the settings would be read at -1 instead of 255. Declaring user settings as byte fixed issue.
+
+ Added "a) Clear user settings" to set menu. This allows us to completely wipe an OpenLog (user settings and config file) to see how it will respond
+ to future firmware changes.
+
+ Improved the file 'size' command.
+
+ Sequential logging is tested and works.
+
+ Receive testing: Using the Test_Sketch found on Github, I am testing the receive reliability at different UART speeds.
+ We need to test a lot of received data. At 57600, 115200, and both from an Arduino (lots of time in between characters becuase of software overhead)
+ and from a raw serial port (almost no time in between characters). I am hoping to make sdfatlib hiccup at 115200, full speed, across a 1MB file. If
+ I can make it fail, then we can start to increase the buffer size and look at how much RAM sdfatlib has left open for the buffer.
+
+ 9600bps from Arduino works fine
+ 57600bps from Arduino drops characters
+ 115200 from Arduino drops characters
+
+ It seems that sdfatlib takes longer to write to the SD card than the original file system from Robert Reigel. I'm thinking perhaps
+ we should create a version of OpenLog firmware that is just sequantial logging, no fancy system menus... It might open up some RAM.
+
+ If only we could get control of the UART from Arduino's clutches, we could probably handle the ring buffer much better. Not sure how to handle UART
+ interrupts without tearing out HardwareSerial.cpp.
+
+ Added README to the Test sketch. Added 115200bps to test sketch.
+
+
+ v2.11 Tested with 16GB microSD. Fixed some general bugs. Lowered power consumption.
+
+ 26136 bytes out of 30720
+
+ Fixed issue 30. I added printing a period ('.') for non-visible ASCII characters during a 'read' command. This cleans up the output a bit. HEX
+ printing is still available.
+
+ Fixed issue 34. When issuing a long command such as "read log00056.txt 100 200 2" (read from spot 100 to spot 200 and print in HEX), the
+ command shell would die at 24 spots. I increased both the general_buffer and 'buffer' in the command shell from 24 to 30. The limit is now
+ 30 characters, so "read log00056.txt 100 20000 2" is allowed.
+
+ Works with a 16GB microSD card! High volume test: loaded 16GB card with 5GB of data. Basic serial tests work. When running at 57600, there
+ is an odd delay. I think it has to do with the file system doing an initial scan for an available cluster. Takes 2-3 seconds before OpenLog
+ returns to normal. This can cause significant data loss.
+
+ Fixing power management in v2. Power down after no characters for 3 seconds now works. Unit drops to 2.35mA in sleep. 7.88mA in sitting
+ RX mode (awake but not receiving anything). There is still a weird bug where the unit comes on at 30mA. After sleep, it comes back at the
+ correct 7-8mA. Is something not getting shut off?
+
+
+ v2.2 Modified append_file() to use a single buffer. Increased HardwareSerial.cpp buffer to 512 bytes.
+
+ More testing at 57600. Record times look to be 2, 5, and zero milliseconds when doing a record. This means that the split buffer doesn't
+ really make a difference? There are some records that take 150ms, 14ms, etc. At 57600bps, that's 7200 bytes/s, 138us per byte. With a 150ms
+ pause, that's 1,086 bytes that need to be buffered while we wait... Grrr. Too many.
+
+ I re-wrote the append_file function to use only one buffer. This allows us to more quickly pull data from the hardware serial buffer. Hardware
+ serial buffer has to be increased manually to 512. This file (hardwareserial.cpp) is stored in the Arduino directory. With testing,
+ it seems like recording is working more solidly at 57600bps. But now I'm seeing glitches at 19200bps so more testing is required before we
+ make this the official OpenLog release.
+
+ Moved input_buffer into within the append function. Attempting to shave bytes of RAM.
+
+
+ v2.21 ringp fork brought in. Wildcard remove and list commands now work. Remove directory now works! Change directory up/down the tree works again.
+
+ 28440 bytes used of 30720.
+
+ ringp brought back many great commands! Thanks ringp!
+ rm LOG*.* works
+ ls *.TXT works
+ cd .. works again
+ ls now correctly shows directories first and files following the directories.
+
+ To remove a directory, you have to navigate into that directory. For example:
+ >cd TEMP (you are now in TEMP directory)
+ >rm -f TEMP (you are now removing TEMP, and you will be pushed back down one level of the tree)
+ >ls (shows files and directories where TEMP directory used to be, but TEMP directory should be gone)
+
+ ringp added new commands:
+ efcount: gives the number of files in the current directory. Example: "efcount" returns "count|3". There are 3 files in the current directory.
+ efinfo <spot>: gives info about the file in <spot>. Example: "efinfo 2" reports "LOG00588.TXT|45". File number 2 is named LOG00588.TXT and is 45 bytes in size.
+ verbose <"on"|"off">: sets whether command errors are verbose (long winded) or just the "!" character. Example: "verbose off" sets verbose off. Then if a
+ command like "blah" is received, then only "!>" is seen from the command line interface. This makes it easier for embedded systems to recognize there
+ was an error. This setting is not recorded to EEPROM.
View
138 OpenLog_v2/FatStructs.h
@@ -1,3 +1,22 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2009 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
#ifndef FatStructs_h
#define FatStructs_h
/**
@@ -9,10 +28,10 @@
* http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
*/
//------------------------------------------------------------------------------
- /** Value for byte 510 of boot block or MBR */
-#define BOOTSIG0 0X55
- /** Value for byte 511 of boot block or MBR */
-#define BOOTSIG1 0XAA
+/** Value for byte 510 of boot block or MBR */
+uint8_t const BOOTSIG0 = 0X55;
+/** Value for byte 511 of boot block or MBR */
+uint8_t const BOOTSIG1 = 0XAA;
//------------------------------------------------------------------------------
/**
* \struct partitionTable
@@ -106,7 +125,7 @@ typedef struct masterBootRecord mbr_t;
*
* The BIOS parameter block describes the physical layout of a FAT volume.
*/
-struct biosParmBlock{
+struct biosParmBlock {
/**
* Count of bytes per sector. This value may take on only the
* following values: 512, 1024, 2048 or 4096
@@ -236,7 +255,7 @@ struct fat32BootSector {
bpb_t bpb;
/** for int0x13 use value 0X80 for hard drive */
uint8_t driveNumber;
- /**used by Windows NT - should be zero for FAT */
+ /** used by Windows NT - should be zero for FAT */
uint8_t reserved1;
/** 0X29 if next three fields are valid */
uint8_t bootSignature;
@@ -255,16 +274,16 @@ struct fat32BootSector {
};
//------------------------------------------------------------------------------
// End Of Chain values for FAT entries
- /** Minimum value for FAT16 EOC. Use to test for EOC. */
-#define FAT16EOC_MIN 0XFFF8
- /** Minimum value for FAT32 EOC. Use to test for EOC. */
-#define FAT32EOC_MIN 0X0FFFFFF8
- /** FAT16 end of chain value used by Microsoft. */
-#define FAT16EOC 0XFFFF
- /** FAT32 end of chain value used by Microsoft. */
-#define FAT32EOC 0X0FFFFFFF
- /** Mask a for FAT32 entry. Entries are 28 bits. */
-#define FAT32MASK 0X0FFFFFFF
+/** FAT16 end of chain value used by Microsoft. */
+uint16_t const FAT16EOC = 0XFFFF;
+/** Minimum value for FAT16 EOC. Use to test for EOC. */
+uint16_t const FAT16EOC_MIN = 0XFFF8;
+/** FAT32 end of chain value used by Microsoft. */
+uint32_t const FAT32EOC = 0X0FFFFFFF;
+/** Minimum value for FAT32 EOC. Use to test for EOC. */
+uint32_t const FAT32EOC_MIN = 0X0FFFFFF8;
+/** Mask a for FAT32 entry. Entries are 28 bits. */
+uint32_t const FAT32MASK = 0X0FFFFFFF;
/** Type name for fat32BootSector */
typedef struct fat32BootSector fbs_t;
@@ -349,46 +368,51 @@ struct directoryEntry {
uint32_t fileSize;
};
//------------------------------------------------------------------------------
-// Macros for directory entries
+// Definitions for directory entries
//
- /** Type name for directoryEntry */
+/** Type name for directoryEntry */
typedef struct directoryEntry dir_t;
- /** escape for name[0] = 0XE5 */
-#define DIR_NAME_0XE5 0X05
- /** name[0] value for entry that is free after being "deleted" */
-#define DIR_NAME_DELETED 0XE5
- /** name[0] value for entry that is free and no allocated entries follow */
-#define DIR_NAME_FREE 0X00
- /** file is read-only */
-#define DIR_ATT_READ_ONLY 0X01
- /** File should hidden in directory listings */
-#define DIR_ATT_HIDDEN 0X02
- /** Entry is for a system file */
-#define DIR_ATT_SYSTEM 0X04
- /** Directory entry contains the volume label */
-#define DIR_ATT_VOLUME_ID 0X08
- /** Entry is for a directory */
-#define DIR_ATT_DIRECTORY 0X10
- /** Old DOS archive bit for backup support */
-#define DIR_ATT_ARCHIVE 0X20
- /** Test value for long name entry. Test is
- d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */
-#define DIR_ATT_LONG_NAME 0X0F
- /** Test mask for long name entry */
-#define DIR_ATT_LONG_NAME_MASK 0X3F
- /** defined attribute bits */
-#define DIR_ATT_DEFINED_BITS 0X3F
- /** Directory entry is part of a long name */
-#define DIR_IS_LONG_NAME(dir)\
- (((dir).attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME)
- /** Mask for file/subdirectory tests */
-#define DIR_ATT_FILE_TYPE_MASK (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY)
- /** Directory entry is for a file */
-#define DIR_IS_FILE(dir) (((dir).attributes & DIR_ATT_FILE_TYPE_MASK) == 0)
- /** Directory entry is for a subdirectory */
-#define DIR_IS_SUBDIR(dir)\
- (((dir).attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY)
- /** Directory entry is for a file or subdirectory */
-#define DIR_IS_FILE_OR_SUBDIR(dir) (((dir).attributes & DIR_ATT_VOLUME_ID) == 0)
-
-#endif //FatStructs_h
+/** escape for name[0] = 0XE5 */
+uint8_t const DIR_NAME_0XE5 = 0X05;
+/** name[0] value for entry that is free after being "deleted" */
+uint8_t const DIR_NAME_DELETED = 0XE5;
+/** name[0] value for entry that is free and no allocated entries follow */
+uint8_t const DIR_NAME_FREE = 0X00;
+/** file is read-only */
+uint8_t const DIR_ATT_READ_ONLY = 0X01;
+/** File should hidden in directory listings */
+uint8_t const DIR_ATT_HIDDEN = 0X02;
+/** Entry is for a system file */
+uint8_t const DIR_ATT_SYSTEM = 0X04;
+/** Directory entry contains the volume label */
+uint8_t const DIR_ATT_VOLUME_ID = 0X08;
+/** Entry is for a directory */
+uint8_t const DIR_ATT_DIRECTORY = 0X10;
+/** Old DOS archive bit for backup support */
+uint8_t const DIR_ATT_ARCHIVE = 0X20;
+/** Test value for long name entry. Test is
+ (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */
+uint8_t const DIR_ATT_LONG_NAME = 0X0F;
+/** Test mask for long name entry */
+uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F;
+/** defined attribute bits */
+uint8_t const DIR_ATT_DEFINED_BITS = 0X3F;
+/** Directory entry is part of a long name */
+static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) {
+ return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME;
+}
+/** Mask for file/subdirectory tests */
+uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
+/** Directory entry is for a file */
+static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
+ return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;
+}
+/** Directory entry is for a subdirectory */
+static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
+ return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;
+}
+/** Directory entry is for a file or subdirectory */
+static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) {
+ return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;
+}
+#endif // FatStructs_h
View
611 OpenLog_v2/OpenLog_v2.pde
@@ -1,33 +1,42 @@
/*
12-3-09
- Copyright SparkFun Electronics© 2010
Nathan Seidle
+ SparkFun Electronics© 2010
spark at sparkfun.com
+ OpenLog hardware and firmware are released under the Creative Commons Share Alike v3.0 license.
+ http://creativecommons.org/licenses/by-sa/3.0/
+ Feel free to use, distribute, and sell varients of OpenLog. All we ask is that you include attribution of 'Based on OpenLog by SparkFun'.
+
+ OpenLog is based on the work of Bill Greiman and sdfatlib:
+ http://code.google.com/p/sdfatlib/
+
OpenLog is a simple serial logger based on the ATmega328 running at 16MHz. The ATmega328
should be able to talk to high capacity (larger than 2GB) SD cards. The whole purpose of this
logger was to create a logger that just powered up and worked. OpenLog ships with standard
57600bps serial bootloader running at 16MHz so you can load new firmware with a simple serial
connection. This makes it compatible with Arduino if needed.
+
+ OpenLog automatically works with 512MB, 1GB, 2GB, 4GB, 8GB, and 16GB microSD cards. We recommend FAT16 for 2GB and smaller cards. We
+ recommend FAT32 for 4GB and larger cards.
- OpenLog runs at 9600bps by default. This is configurable to 2400, 9600, 57600, and 115200bps. We recommend
- you attach a serial connection to reconfigure the unit to work at a different serial speed, but you
- should be able to do it in software.
+ OpenLog runs at 9600bps by default. This is configurable to 2400, 4800, 9600, 19200, 57600, and 115200bps. You can alter all settings
+ including baud rate and escape characters by editing config.txt found on OpenLog.
Type '?' to get a list of supported commands.
- During power up, you will see '12>'. '1' indicates the serial connection is established. '2' indicates
- the SD card has been successfully initialized. '>' indicates OpenLog is ready to receive commands.
+ During power up, you will see '12<'. '1' indicates the serial connection is established. '2' indicates
+ the SD card has been successfully initialized. '<' indicates OpenLog is ready to receive serial characters.
- Recording constant 115200bps datastreams are supported. Throw it everything you've got!
+ Recording constant 115200bps datastreams are supported. Throw it everything you've got! To acheive this maximum record rate, please use the
+ SD card formatter from : http://www.sdcard.org/consumers/formatter/. The fewer files on the card, the faster OpenLog is able to begin logging.
+ 200 files is ok. 2GB worth of music and pictures is not.
- 'cd ..' is a bit weird. Normally it's 'cd..' but to change to a lower dir, use 'cd ..'
+ To a lower dir, use 'cd ..' instead of 'cd..'.
- Currently, the firmware supports creating a new file or directory up to 16 characters including the
- '.' and extension. "123456789012.txt" is the longest name. Any longer and the module will re-initialize
- as if there was a variable sizeof error.
+ Only standard 8.3 file names are supported. "12345678.123" is acceptable. "123456789.123" is not.
- Capital letters, white space, and other characters are supported ("Hi there#$_.txt").
+ All file names are pushed to upper case. "NewLog.txt" will become "NEWLOG.TXT".
Type 'set' to enter baud rate configuration menu. Select the baud rate and press enter. You will then
see a message 'Going to 9600bps...' or some such message. You will need to power down OpenLog, change
@@ -40,9 +49,6 @@
Please note: The preloaded STK500 serial bootloader is 2k, and begins at 0x7800 (30,720). If the code is
larger than 30,719 bytes, you will get verification errors during serial bootloading.
- SD vs HCSD configuration is found in sd_raw_config.h - Currently only 512MB, 1GB, 2GB, and some
- 4GB cards work (not yet compatible with HCSD cards).
-
STAT1 LED is sitting on PD5 (Arduino D5) - toggles when character is received
STAT2 LED is sitting on PB5 (Arduino D13) - toggles when SPI writes happen
@@ -50,10 +56,10 @@
No SD card - 3 blinks
Baud rate change (requires power cycle) - 4 blinks
- During an append, OpenLog will buffer 512 characters at a time. That means that if the system loses power
- while reading in characters, you may loose up to, but no more than, 511 characters. This is important for low
- power systems where you may not know when the battery or power will die. OpenLog should record each buffer as
- it receives each 512 byte chunk. The only way to exit an append is with Ctrl+z (ASCII 26).
+ OpenLog regularly shuts down to conserve power. If after 1.5 seconds no characters are received, OpenLog will record any unsaved characters
+ and go to sleep. OpenLog will automatically wake up and continue logging the instand a new character is received. If power is lost during normal
+ operation, OpenLog should lose a maximum of the RX_BUFF / 2. This is currently a max of 350 characters. It's actually quite hard to get into this scenario
+ and is rare with normal operation.
8mA idle
18mA actively writing
@@ -62,295 +68,99 @@
TX-O pin will not be greater than 3.3V. This may cause problems with some systems - for example if your
attached microcontroller requires 4V minimum for serial communication (this is rare).
-
- v1.1
- Adding better defines for EEPROM settings
- Adding new log and sequential log functions.
-
- Code is acting very weird with what looks to be stack crashes. I can get around this by turning the optimizer off ('0').
- Found an error : EEPROM functions fail when optimizer is set to '0' or '1'.
- sd-reader_config.h contains flag for USE_DYNAMIC_MEMORY
-
- Looks like tweaking the optimization higher causes the asm("nop"); to fail inside the append_file routine. Changing this to
- delay_us(1); works.
-
- I have a sneaking suspicion that I was having buffer overrun problems when defining the input_buffer at 1024 bytes. The
- ATmega328 should have enough RAM (2K) but weird reset errors were occuring. With the buffer at 512bytes, append_file runs
- just fine and is able to log at 115200 at a constant data rate.
-
- Added file called 'lots-o-text.txt' to version control. This text contains easy to scan text to be used for full data
- rate checking and testing.
-
-
- v1.2
- ringp added:
- Adding support for splitting command line parameters into arguments
- Adding support for reading files sequencially
- read <filename> <start> <length>
- New log now for sequencial log functions supports 0-65535 files
- Adding support for wildcard listing or deletion of files
- ls <wildcard search>
- rm <wildcard delete>
-
- Really great additions. Thanks ringp!
-
- Nate added error testing within newlog()
- Checks to see if we have 65534 logs. If so, error out to command prompt with "!Too many logs:1"
-
-
- v1.3
- Added sd_raw_sync() inside append_file. I believe this was why tz1's addition of the timeout buffer update feature
- was not working. Auto buffer update now working. So if you don't send anything to OpenLog for 5 seconds,
- the buffer will automatically record/update.
-
- Need to create 'Testing' page to outline the battery of tests we need to throw at any OpenLog after a firmware
- submission and update is complete.
-
- Testing
- create 40,000 logs
-
- Record at full speed:
- Run at full 115200, load lotsoftext.txt and verify no characters are dropped.
-
- Detect too many logs:
- Create new log at 65533 (do this by editing 'zero' function to set EEPROM to 0xFF and oxFD)
- and power cycle. Verify unit starts new log. Power cycle and verify unit errors out and drops to command prompt.
-
- Record buffer after timeout:
- Create new log. Type 20 characters and wait 5 seconds. Unit should auto-record buffer. Power down unit.
- Power up unit and verify LOG has 20 characters recorded.
-
-
- v1.4
- Added exit options to the two menus (set and baud)
- Also added display of current settin to two menus (Ex: "Baud currently: 57600bps")
-
- Added '!' infront of 'error opening'. This pops up if there is an error while trying to append
- to a freshly created new log (ex: LOG00548.txt is created, then errors out because it cannot append).
- '!' was added so that user can parse against it.
-
- Replicated logging errors at 57600 using 5V Arduino
- Unit would systematically glitch during logging of 111054 bytes
-
- Increasing buffer to 1000 characters caused URU error.
- URU: Unit Resets Unexpectedly
-
- To recreate URU error. Type "append ". Include the space. If you get "!error opening", then things are
- fine. If you get "!error opening#" where # is a weird character, then type 'ls' and the unit will
- unexpectedly reset (URU error). I believe this is attributed to a memory overrun somewhere in the
- FAT system.
-
- Changed buffer size to 900 and declared the character buffer as volatile
- #define BUFF_LEN 900
- volatile char input_buffer[BUFF_LEN];
-
- This increase to the buffer allows for clean logging of 444055 bytes with no URU errors.
-
- Experimenting with Scott's SD cards (customer gave cards on loan for recreating logging errors):
- Card with single ~740mb file produces errors when trying to open/append to new log.
- Card with less stuff on it logs full 444055 bytes correctly.
-
-
- v1.5
- Added 4800bps and 19200bps support
-
- Added power saving features. Current consumption at 5V is now:
- In default append mode:
- 6.6/5.5mA while receiving characters (LED On/Off)
- 2.1mA during idle
- In command mode: 3.2/2.1mA (LED On/Off)
-
- So if you're actively throwing characters at the logger, it will be ~6mA. If you send the logger
- characters then delay 5-10 seconds, current will be ~2.5mA. (Unit records the characters in the buffer
- and goes into idle more if no characters are received after 5 seconds)
-
- These power savings required some significant changes to uart.c / uart_getc()
+ OpenLog has progressed significantly over the past year. Please see Changes.txt or GitHub for a full change log.
- v1.51 check_emergency_reset, default break character is ctrl+z 3 times, example Arduino sketch
-
- Added function from mungewell - check_emergency_reset. This has improved testing of the RX pin.
- There was potential to get a false baud reset. There is still a chance but it's now much less likely.
-
- If OpenLog is attached to a Arduino, during bootloading of the Arduino, ctrl+z will most likely be sent
- to the Arduino from the computer. This character will cause OpenLog to drop to command mode - probably
- not what we want. So I added user selectable character (ctrl+x or '$' for example) and I added
- user selectable number of escape characters to look for in a row (example is 1 or 2 or 3, '$$$' is a
- common escape sequence). The default is now ctrl+z sent 3 times in a row.
-
- Added an example Arduino sketch (from ScottH) to GitHub so that people can easily see how to send characters to
- OpenLog. Not much to it, but it does allow us to test large amounts of text thrown at OpenLog
- at 57600bps.
-
-
- v1.6 Adding config file.
-
- What happens if I reset the system by pulling RX low, but the config file has corrupt values in it?
-
- If config file has corrupt values in it, system will default to known values 9600/ctrl+z/3/newlog
-
- If config file is empty, system resets to known values
-
- After some massive testing, and lots of code to check for illegal states, it looks to be pretty stable.
- The only problem is that we're running out of RAM. The buffer had to be decreased from 900 bytes
- to 700 bytes to facilitate all the config file checking. Testing at 57600bps, unit runs very well
- over 40kb test file on straight RS232 connection. That's pretty good. Testing at 115200 on straight
- connection, unit will drop a buffer every once and a while. Not great, but not much we can do if the
- SD card times out for ~150ms while it's writing.
- 8 bits to the byte plus a start/stop bit = 10 bits per byte
-
- @ 9600bps = 960 bytes per second. Buffer will last for 729ms
- @ 57600bps = 5760 bytes per second. Buffer will last for 121ms
- @ 115200bps = 11520 bytes per second. Buffer will last for 60.7ms
-
- So if the SD card pauses for more than 60ms, 115200 will have lost data, sometimes. All other baud rates
- should be covered for the most part.
-
- SD cards with larges amounts of data will have increased pause rates. Always use a clean card where possible.
-
-
- v1.61 Small PCB change. Fixed version # in help menu.
-
- Fixed the firmware version in the help menu to v1.61.
-
- Updated Eagle files to Eagle v5.9. Fixed weird airwire. Changed D1 LED from Green to Blue.
- Will only affect new production after 4-28-10.
-
- Closed some tickets and wrote some more example Arduino code:
- http://forum.sparkfun.com/viewtopic.php?t=21438
-
-
- v2.0 - 25986 bytes out of 30720
- Welcome to version 2! We've moved from Roland Riegel's FAT library to Bill Greiman's sdfatlib. OpenLog now works with SD cards
- up to 16GB (that is the current largest microSD card we can get our hands on). OpenLog automatically detects and works with FAT16/FAT32
- file systems. It also automatically works with normal SD cards as well as SDHC cards.
-
- Almost all the previous commands have been ported from v1 to v2. The current commands that do not work:
- cd.. - does not work. You can change to an upper directory, but you cannot navigate back down the tree.
- cat - this command was depricated. HEX printing is now done with the 'read' command. We've added a 5th argument to select between ASCII and HEX printing.
- Wild cards do not yet work. So rm and ls do not have wild cards enabled - yet. Help us out!
-
- Porting OpenLog to work directly under Arduino to work with sdfatlib (http://code.google.com/p/sdfatlib/) by Bill Greiman.
-
- sdfatlib intrinsically supports FAT16, FAT32 as well as SD and HCSD cards. In a word, it's amazing.
-
- Needs to be done:
- Done - Get config file reading/loading working
- Document config file in wiki: if no config file is found, current system settings are used. If config is found, system switches to settings found in file. If system settings are changed, then config file is changed and system uses new settings immediately.
- Done - We don't want to constantly record a new config file on each power on. Only record when there is a change.
- Get cd.. working
- Seperate OpenLog_v2 into multiple files
- Re-test too many log files created in the newlog setting - 65535. Potentially create thousands of files and see how sdfatlib handles it.
- Done - Test sequential logging.
- Get wild card support working for ls and rm
- Get backspace working
- Test rm with directories, and directory wildcards? Maybe not.
- Get power save working
- Test compile on a computer that doesn't have WinAVR
-
- Test commands:
- new - works, also in sub dirs
- append - works, also in sub dirs
- rm - works, but does not yet support wild cards.
- md - works, also in sub dirs
- cd - you can change up to a sub-directory, but you cannot navigate back down the tree. The current work around is to type 'init'. This will re-init the card and set the directory back to root.
- ls - works pretty well but does not yet support wild cards. Shows directories, files, and file sizes. Would be cool if it listed dirs first.
- read - works well. Tested 0, 1, 2, 3, 4, and 5 arguments (included and left off). Fails gracefully. Now prints in HEX as well!
- size - works well
- disk - works well, prints more information than ever before!
- init - works well
- sync - works, but not really tested
- cat - I've decided to drop this command. You can now print in hex using the read command and using a 5th argument as '1' for ASCII (default) and '2' for HEX.
-
- set - works well
- baud - works well
-
-
- v2.1 - Power save not working. Fixed issue 35. Dropping characters at 57600bps.
- 26058 bytes out of 30720
- Fixed a bug found by Salient (Issue 35). User settings where declared at chars which allowed them to be signed. If a user went from old firmware, to v2,
- the safety checks would fail because the settings would be read at -1 instead of 255. Declaring user settings as byte fixed issue.
-
- Added "a) Clear user settings" to set menu. This allows us to completely wipe an OpenLog (user settings and config file) to see how it will respond
- to future firmware changes.
+ v2.21 ringp fork brought in. Wildcard remove and list commands now work. Remove directory now works! Change directory up/down the tree works again.
- Improved the file 'size' command.
+ 28440 bytes used of 30720.
- Sequential logging is tested and works.
+ ringp brought back many great commands! Thanks ringp!
+ rm LOG*.* works
+ ls *.TXT works
+ cd .. works again
+ ls now correctly shows directories first and files following the directories.
- Receive testing: Using the Test_Sketch found on Github, I am testing the receive reliability at different UART speeds.
- We need to test a lot of received data. At 57600, 115200, and both from an Arduino (lots of time in between characters becuase of software overhead)
- and from a raw serial port (almost no time in between characters). I am hoping to make sdfatlib hiccup at 115200, full speed, across a 1MB file. If
- I can make it fail, then we can start to increase the buffer size and look at how much RAM sdfatlib has left open for the buffer.
+ To remove a directory, you have to navigate into that directory. For example:
+ >cd TEMP (you are now in TEMP directory)
+ >rm -f TEMP (you are now removing TEMP, and you will be pushed back down one level of the tree)
+ >ls (shows files and directories where TEMP directory used to be, but TEMP directory should be gone)
- 9600bps from Arduino works fine
- 57600bps from Arduino drops characters
- 115200 from Arduino drops characters
+ ringp added new commands:
+ efcount: gives the number of files in the current directory. Example: "efcount" returns "count|3". There are 3 files in the current directory.
+ efinfo <spot>: gives info about the file in <spot>. Example: "efinfo 2" reports "LOG00588.TXT|45". File number 2 is named LOG00588.TXT and is 45 bytes in size.
+ verbose <"on"|"off">: sets whether command errors are verbose (long winded) or just the "!" character. Example: "verbose off" sets verbose off. Then if a
+ command like "blah" is received, then only "!>" is seen from the command line interface. This makes it easier for embedded systems to recognize there
+ was an error. This setting is not recorded to EEPROM.
- It seems that sdfatlib takes longer to write to the SD card than the original file system from Robert Reigel. I'm thinking perhaps
- we should create a version of OpenLog firmware that is just sequantial logging, no fancy system menus... It might open up some RAM.
- If only we could get control of the UART from Arduino's clutches, we could probably handle the ring buffer much better. Not sure how to handle UART
- interrupts without tearing out HardwareSerial.cpp.
+ v2.3 Migrated to v10.10.10 of sdfatlib. Moved to inline RX interrupt and buffer. Improved the ability to receive a constant stream at 57600bps.
- Added README to the Test sketch. Added 115200bps to test sketch.
+ 27334 bytes out of 30720.
+ Remember - we had to completely butcher HardwareSerial.cpp so a normal Arduino installation will not work.
+ C:\arduino-xxxx\hardware\arduino\cores\arduino\HardwareSerial.cpp
- v2.11 Tested with 16GB microSD. Fixed some general bugs. Lowered power consumption.
+ I removed the receive interupt handler from HardwareSerial.cpp so that we can deal directly with USART_RX_vect in the main code. This allows
+ us to return to the way OpenLog used to operate - by having one buffer split in half. Once one half fills, it is recorded to SD while the other
+ half fills up. This dramatically decreases the time spent in function calls and SD recording, which leads to many fewer characters dropped.
- 26136 bytes out of 30720
+ The change log at the top of the main code got so large I've moved it to a version controlled "Changes.txt" file.
- Fixed issue 30. I added printing a period ('.') for non-visible ASCII characters during a 'read' command. This cleans up the output a bit. HEX
- printing is still available.
+ By making all these changes, I have broken many things. Ringp - I could use your help here. I apologize for stomping on so much of your work. I was not
+ good enough to figure out how to re-link from the old function calls to the new sdfatlib setup.
- Fixed issue 34. When issuing a long command such as "read log00056.txt 100 200 2" (read from spot 100 to spot 200 and print in HEX), the
- command shell would die at 24 spots. I increased both the general_buffer and 'buffer' in the command shell from 24 to 30. The limit is now
- 30 characters, so "read log00056.txt 100 20000 2" is allowed.
+ Backspace is broken - ringp, I saw this fix in one of your commits, but looking at the code, I don't see how it is supposed to work. Either way, we still
+ get 0x08 when trying to backspace.
- Works with a 16GB microSD card! High volume test: loaded 16GB card with 5GB of data. Basic serial tests work. When running at 57600, there
- is an odd delay. I think it has to do with the file system doing an initial scan for an available cluster. Takes 2-3 seconds before OpenLog
- returns to normal. This can cause significant data loss.
+ Search for //Error in main pde
+ ls is not working fully
+ remove is not working
+ fileInfo is not working
- Fixing power management in v2. Power down after no characters for 3 seconds now works. Unit drops to 2.35mA in sleep. 7.88mA in sitting
- RX mode (awake but not receiving anything). There is still a weird bug where the unit comes on at 30mA. After sleep, it comes back at the
- correct 7-8mA. Is something not getting shut off?
+ New sdfatlib doesn't have SdFat.cpp so fileInfo doesn't work. These function calls are marked with //Error
+ I have chosen to dis-allow deprecated functions:
+ #define ALLOW_DEPRECATED_FUNCTIONS 0
+ This forced some trivial changes to the SD write and new file creation function calls. I believe we've successfully migrated to the new version of sdfatlib.
- v2.2 Modified append_file() to use a single buffer. Increased HardwareSerial.cpp buffer to 512 bytes.
+ In the command_shell / read_line function : It may be better to pull directly from the UART buffer and use the RX interrupt. For now, we brute force it.
- More testing at 57600. Record times look to be 2, 5, and zero milliseconds when doing a record. This means that the split buffer doesn't
- really make a difference? There are some records that take 150ms, 14ms, etc. At 57600bps, that's 7200 bytes/s, 138us per byte. With a 150ms
- pause, that's 1,086 bytes that need to be buffered while we wait... Grrr. Too many.
+ Because of all these changes, I need to re-test power consumption. For now, I'm confident it's low enough.
- I re-wrote the append_file function to use only one buffer. This allows us to more quickly pull data from the hardware serial buffer. Hardware
- serial buffer has to be increased manually to 512. This file (hardwareserial.cpp) is stored in the Arduino directory. With testing,
- it seems like recording is working more solidly at 57600bps. But now I'm seeing glitches at 19200bps so more testing is required before we
- make this the official OpenLog release.
+ Testing with 512 buffer array size
+ 1GB @ 57600 - dropped very little out of 3 tests
+ 1GB @ 115200 - dropped very little out of 2 tests
+ 8GB @ 57600 - Formatted using the sd formater (32k byte allocation size). Dropped nothing.
+ 8GB @ 115200 - dropped very little, dropped none
+ 16GB w/ Lots of files @ 57600 - Drops the first part of the file because of start up delay?
+ 16GB w/ Lots of files @ 115200
- Moved input_buffer into within the append function. Attempting to shave bytes of RAM.
+ 1024 array size (and 800) does not run
+ Testing with 700 buffer array size
+ 1GB @ 57600 - 110300 out of 111000 bytes, 110300/111000,
+ 1GB @ 115200 - 111000/111000!, 109600/111000
+ 8GB @ 57600 - 109000/111000, 111000/111000!,
+ 8GB @ 115200 - 111000/111000!, 111000/111000!,
+ 16GB w/ Lots of files @ 57600 - 85120/111000, 85120/111000
+ 16GB w/ Lots of files @ 115200 - 56420 (but once it got going, log looks good). 56420.
- v2.21 ringp fork brought in. Wildcard remove and list commands now work. Remove directory now works! Change directory up/down the tree works again.
+ I am seeing long delays on cards with lots of files. In the above tests, the 16GB test card is a good example. It has 2GB worth of random files in a sub directory.
+ After OpenLog boots, goes to '12<'. After I send ~500 characters OpenLog freezes for a couple seconds, then returns to normal, very fast, operation. During
+ that down time, I believe sdfatlib is searching for an open cluster. The odd thing is that after the cluster is established (after the initial down time) OpenLog
+ performs excellently. I am hoping to create a faux file or pre-write and save to the file or some how get this allocation done before we report the
+ '12<' indicating we are ready. That way, if a card does fill up, as long as the host system is checking for '<', it doesn't matter how long it takes
+ sdfatlib to find the next free cluster.
- 28440 bytes used of 30720.
+ You can see that we drop 700 bytes at a time. That's a bit odd - I'd expect to drop half or 350 at a time.
+ What happens if we shrink the array size to say 256? To be expected, this is bad - way more instances of dropped characters.
- ringp brought back many great commands! Thanks ringp!
- rm LOG*.* works
- ls *.TXT works
- cd .. works again
- ls now correctly shows directories first and files following the directories.
+ Added blink for each test to the OpenLog_Test sketch so we can see as the test progresses.
- To remove a directory, you have to navigate into that directory. For example:
- >cd TEMP (you are now in TEMP directory)
- >rm -f TEMP (you are now removing TEMP, and you will be pushed back down one level of the tree)
- >ls (shows files and directories where TEMP directory used to be, but TEMP directory should be gone)
+ http://www.sdcard.org/consumers/formatter/ is the site for SD card formatting. It looks like this program takes a guess at the correct block size. This could
+ help a lot in the future.
- ringp added new commands:
- efcount: gives the number of files in the current directory. Example: "efcount" returns "count|3". There are 3 files in the current directory.
- efinfo <spot>: gives info about the file in <spot>. Example: "efinfo 2" reports "LOG00588.TXT|45". File number 2 is named LOG00588.TXT and is 45 bytes in size.
- verbose <"on"|"off">: sets whether command errors are verbose (long winded) or just the "!" character. Example: "verbose off" sets verbose off. Then if a
- command like "blah" is received, then only "!>" is seen from the command line interface. This makes it easier for embedded systems to recognize there
- was an error. This setting is not recorded to EEPROM.
*/
#include "SdFat.h"
@@ -380,6 +190,21 @@
#define sbi(port, port_pin) ((port) |= (uint8_t)(1 << port_pin))
#define cbi(port, port_pin) ((port) &= (uint8_t)~(1 << port_pin))
+//#define RX_BUFF_SIZE 1024 //This larger buffer size does work but may not work in full OpenLog bells and whistles
+//#define RX_BUFF_SIZE 800 //Bad
+#define RX_BUFF_SIZE 700 //Works
+//#define RX_BUFF_SIZE 512
+//#define RX_BUFF_SIZE 256 //Drops lots
+char rxBuffer[RX_BUFF_SIZE];
+int rxSpot;
+
+//The very important receive interrupt handler
+SIGNAL(USART_RX_vect)
+{
+ rxBuffer[rxSpot++] = UDR0;
+ if(rxSpot == RX_BUFF_SIZE) rxSpot = 0;
+}
+
char general_buffer[30];
#define FOLDER_TRACK_DEPTH 15
char folderTree[FOLDER_TRACK_DEPTH][12];
@@ -503,15 +328,15 @@ void setup(void)
#endif
//Setup SD & FAT
- if (!card.init()) {
+ if (!card.init(SPI_FULL_SPEED)) {
PgmPrint("error card.init");
blink_error(ERROR_SD_INIT);
} // initialize the SD card
- if (!volume.init(card)) {
+ if (!volume.init(&card)) {
PgmPrint("error volume.init");
blink_error(ERROR_SD_INIT);
} // initialize a FAT volume
- if (!currentDirectory.openRoot(volume)) {
+ if (!currentDirectory.openRoot(&volume)) {
PgmPrint("error openRoot");
blink_error(ERROR_SD_INIT);
} // open the root directory
@@ -607,7 +432,7 @@ void newlog(void)
sprintf(new_file_name, "LOG%05d.TXT", new_file_number); //Splice the new file number into this file name
//Try to open file, if fail (file doesn't exist), then break
- if (file.open(currentDirectory, new_file_name, O_CREAT | O_EXCL | O_WRITE)) break;
+ if (file.open(&currentDirectory, new_file_name, O_CREAT | O_EXCL | O_WRITE)) break;
}
file.close(); //Close this new file we just opened
//file.writeError = false; // clear any write errors
@@ -641,7 +466,7 @@ void seqlog(void)
char seq_file_name[13] = "SEQLOG00.TXT";
//Try to create sequential file
- if (!file.open(currentDirectory, seq_file_name, O_CREAT | O_WRITE))
+ if (!file.open(&currentDirectory, seq_file_name, O_CREAT | O_WRITE))
{
PgmPrint("Error creating SEQLOG\n");
return;
@@ -661,21 +486,13 @@ void seqlog(void)
//Returns 1 on success
uint8_t append_file(char* file_name)
{
- //44051
- //This is the size of the receive buffer. The bigger it is, the less likely we will overflow the buffer while doing a record to SD.
- //But we have limited amounts of RAM (~1100 bytes)
-#define BUFF_LEN 50 //50 works well. Too few and we will call file.write A LOT. Too many and we run out of RAM.
- //#define BUFF_LEN 400 //Fails horribly for some reason. Oh right, readSpot only goes to 255.
- //#define BUFF_LEN 100 //Works well.
- char inputBuffer[BUFF_LEN];
+ int checkedSpot;
char escape_chars_received = 0;
- byte readSpot = 0; //Limited to 255
- byte incomingByte;
// O_CREAT - create the file if it does not exist
// O_APPEND - seek to the end of the file prior to each write
// O_WRITE - open for write
- if (!file.open(currentDirectory, file_name, O_CREAT | O_APPEND | O_WRITE)) {
+ if (!file.open(&currentDirectory, file_name, O_CREAT | O_APPEND | O_WRITE)) {
if ((feedback_mode & EXTENDED_INFO) > 0)
error("open1");
}
@@ -689,10 +506,15 @@ uint8_t append_file(char* file_name)
digitalWrite(statled1, HIGH); //Turn on indicator LED
//Clear out the serial buffer
- Serial.flush();
+ rxSpot = 0;
+ checkedSpot = 0;
+
+ //Start UART buffered interrupts
+ UCSR0B |= (1<<RXCIE0); //Enable receive interrupts
+ sei(); //Enable interrupts
//Start recording incoming characters
- //HardwareSerial.cpp has a buffer tied to the interrupt. We increased this buffer to 512 bytes
+ // //HardwareSerial.cpp has a buffer tied to the interrupt. We increased this buffer to 512 bytes
//As characters come in, we read them in and record them to FAT.
while(1){
uint16_t timeout_counter = 0;
@@ -716,67 +538,90 @@ uint8_t append_file(char* file_name)
//file.close();
//if (!file.open(currentDirectory, file_name, O_CREAT | O_APPEND | O_WRITE)) error("open1");
- while(!Serial.available()){ //Wait for characters to come in
+ while(checkedSpot == rxSpot){ //Wait for characters to come in
if(timeout_counter++ > 1200){ //If we haven't seen a character for about 3 seconds, then record the buffer, sync the SD, and shutdown
timeout_counter = 0;
- if(readSpot != 0){ //There is unrecorded stuff sitting in the buffer
- //Record the buffer
- if(file.write((byte*)inputBuffer, readSpot) != readSpot)
- if ((feedback_mode & EXTENDED_INFO) > 0)
- PgmPrintln("error writing to file");
- }
+ if(checkedSpot != 0 && checkedSpot != (RX_BUFF_SIZE/2)) //There is stuff in buffer to record before we go to sleep
+ {
+ if(checkedSpot < (RX_BUFF_SIZE/2)) {
+ file.write(rxBuffer, checkedSpot); //Record first half the buffer
+ }
+ else { //checked_spot > (BUFF_LEN/2)
+ file.write(rxBuffer + (RX_BUFF_SIZE/2), checkedSpot - (RX_BUFF_SIZE/2)); //Record second half the buffer
+ }
- file.sync(); //Push these new file.writes to the SD card
- Serial.flush(); //Clear out the current serial buffer. This is needed if the buffer gets overrun. OpenLog will fail to read the escape character if
- //the buffer gets borked.
+ // rxSpot may have moved while we , copy
+ unsigned spot = checkedSpot > RX_BUFF_SIZE/2 ? RX_BUFF_SIZE/2 : 0;
+ unsigned sp = spot; // start of new buffer
- //Reset the points so that we don't record these freshly recorded characters a 2nd time, when the unit receives more characters
- readSpot = 0;
+ cli();
+
+ while(checkedSpot != rxSpot)
+ {
+ rxBuffer[spot++] = rxBuffer[checkedSpot++]; //Error - We are not checking for escape characters in here
+ if( checkedSpot >= RX_BUFF_SIZE )
+ checkedSpot = 0;
+ }
+
+ rxSpot = spot; // set insertion to end of copy
+ checkedSpot = sp; // reset checked to beginning of copy
+
+ sei();
+
+ file.sync(); //Push these new file.writes to the SD card
+ }
//Now power down until new characters to arrive
- while(!Serial.available()){
- digitalWrite(statled1, LOW); //Turn off stat LED to save power
- sleep_mode(); //Stop everything and go to sleep. Wake up if serial character received
+ while(checkedSpot == rxSpot){
+ digitalWrite(STAT1, LOW); //Turn off stat LED to save power
+ //sleep_mode(); //Stop everything and go to sleep. Wake up if serial character received
}
}
delay(1); //Hang out for a ms
}
- incomingByte = Serial.read(); //Grab new character from hardwareserial.cpp buffer (could be 512 bytes)
-
//Scan for escape character
- if(incomingByte == setting_escape_character){
+ if(rxBuffer[checkedSpot] == setting_escape_character){
#if DEBUG
Serial.print("!");
#endif
- if(++escape_chars_received == setting_max_escape_character) break;
+ if(++escape_chars_received == setting_max_escape_character){
+ //Disable interrupt and we're done!
+ cli();
+ UCSR0B &= ~(1<<RXCIE0); //Clear receive interrupt enable
+ break;
+ }
}
else
escape_chars_received = 0;
- inputBuffer[readSpot++] = incomingByte; //Record character to the local buffer
+ checkedSpot++;
- if(readSpot == BUFF_LEN){ //If we've filled the local small buffer, pass it to the sd write function.
- //Record the buffer
- if(file.write((byte*)inputBuffer, BUFF_LEN) != BUFF_LEN){
- if ((feedback_mode & EXTENDED_INFO) > 0)
- PgmPrintln("error writing to file");
- break;
- }
+ if(checkedSpot == (RX_BUFF_SIZE/2)) { //We've finished checking the first half the buffer
+ file.write(rxBuffer, RX_BUFF_SIZE/2); //Record first half the buffer
+ }
- readSpot = 0; //Wrap the buffer
+ if(checkedSpot == RX_BUFF_SIZE){ //We've finished checking the second half the buffer
+ checkedSpot = 0;
+ file.write(rxBuffer + (RX_BUFF_SIZE/2), RX_BUFF_SIZE/2); //Record second half the buffer
}
STAT1_PORT ^= (1<<STAT1); //Toggle the STAT1 LED each time we receive a character
} //End while - escape character received or error
//Upon receiving the escape character, we may still have stuff left in the buffer, record the last of the buffer to memory
- if(readSpot != BUFF_LEN){
- //Record the buffer
- if(file.write((byte*)inputBuffer, readSpot) != readSpot)
- if ((feedback_mode & EXTENDED_INFO) > 0)
- PgmPrintln("error writing to file");
+ if(checkedSpot == 0 || checkedSpot == (RX_BUFF_SIZE/2))
+ {
+ //Do nothing, we already recorded the buffers right before catching the escape character
+ }
+ else if(checkedSpot < (RX_BUFF_SIZE/2))
+ {
+ file.write(rxBuffer, checkedSpot); //Record first half the buffer
+ }
+ else //checkedSpot > (RX_BUFF_SIZE/2)
+ {
+ file.write(rxBuffer + (RX_BUFF_SIZE/2), checkedSpot - (RX_BUFF_SIZE/2)); //Record second half the buffer
}
file.sync();
@@ -806,13 +651,13 @@ uint8_t gotoDir(char *dir)
currentDirectory.close();
// open the root directory
- if (!currentDirectory.openRoot(volume)) error("openRoot");
+ if (!currentDirectory.openRoot(&volume)) error("openRoot");
int8_t index = getNextFolderTreeIndex() - 1;
if (index >= 0)
{
for (int8_t iTemp = 0; iTemp < index; iTemp++)
{
- if (!(tmp_var = subDirectory.open(currentDirectory, folderTree[iTemp], O_READ)))
+ if (!(tmp_var = subDirectory.open(&currentDirectory, folderTree[iTemp], O_READ)))
break;
currentDirectory = subDirectory; //Point to new directory
@@ -828,7 +673,7 @@ uint8_t gotoDir(char *dir)
}
else
{
- if (!(tmp_var = subDirectory.open(currentDirectory, dir, O_READ))) {
+ if (!(tmp_var = subDirectory.open(&currentDirectory, dir, O_READ))) {
if ((feedback_mode & EXTENDED_INFO) > 0)
{
PgmPrint("directory not found: ");
@@ -847,6 +692,11 @@ uint8_t gotoDir(char *dir)
}
void command_shell(void)
{
+ //Serial.begin causes the receive interrupt to turn on
+ //This is bad for command_shell that relies on non-interrupt driven line reads
+ cli();
+ UCSR0B &= ~(1<<RXCIE0); //Clear receive interrupt enable
+
//provide a simple shell
char buffer[30];
uint8_t tmp_var;
@@ -893,7 +743,7 @@ void command_shell(void)
currentDirectory.close();
// open the root directory
- if (!currentDirectory.openRoot(volume)) error("openRoot");
+ if (!currentDirectory.openRoot(&volume)) error("openRoot");
PgmPrintln("File system initialized");
#ifdef INCLUDE_SIMPLE_EMBEDDED
@@ -957,7 +807,8 @@ void command_shell(void)
Serial.println(volume.fatType(), DEC);
}
- currentDirectory.ls(LS_SIZE, 0, &wildcmp, get_cmd_arg(1));
+ //Error currentDirectory.ls(LS_SIZE, 0, &wildcmp, get_cmd_arg(1));
+ currentDirectory.ls(LS_SIZE);
#ifdef INCLUDE_SIMPLE_EMBEDDED
command_succedded = 1;
@@ -977,7 +828,7 @@ void command_shell(void)
continue;
SdFile newDirectory;
- if (!newDirectory.makeDir(currentDirectory, command_arg)) {
+ if (!newDirectory.makeDir(&currentDirectory, command_arg)) {
if ((feedback_mode & EXTENDED_INFO) > 0)
{
PgmPrintln("error creating directory: ");
@@ -1009,7 +860,7 @@ void command_shell(void)
//Calling rmRfStart() will result in OpenLog rebooting.
if (strncmp_P(command_arg, PSTR("-f"), 2) == 0)
{
- if (file.open(currentDirectory, command_arg, O_READ))
+ if (file.open(&currentDirectory, command_arg, O_READ))
file.close(); //There is a file called "-f"
else
{
@@ -1023,7 +874,8 @@ void command_shell(void)
}
//Argument 2: File name or file wildcard removal
- uint32_t filesDeleted = currentDirectory.remove(&wildcmp, get_cmd_arg(1), &removeErrorCallback);
+ //Error uint32_t filesDeleted = currentDirectory.remove(&wildcmp, get_cmd_arg(1), &removeErrorCallback);
+ uint32_t filesDeleted = 0;
if ((feedback_mode & EXTENDED_INFO) > 0)
{
Serial.print(filesDeleted);
@@ -1049,7 +901,7 @@ void command_shell(void)
tmp_var = gotoDir(command_arg);
#ifdef INCLUDE_SIMPLE_EMBEDDED
- command_succedded = tmp_var;
+ command_succedded = tmp_var;
#endif
}
@@ -1061,7 +913,7 @@ void command_shell(void)
continue;
//search file in current directory and open it
- if (!file.open(currentDirectory, command_arg, O_READ)) {
+ if (!file.open(&currentDirectory, command_arg, O_READ)) {
if ((feedback_mode & EXTENDED_INFO) > 0)
{
PgmPrint("Failed to open file ");
@@ -1135,7 +987,7 @@ void command_shell(void)
continue;
//search file in current directory and open it
- if (!file.open(currentDirectory, command_arg, O_WRITE)) {
+ if (!file.open(&currentDirectory, command_arg, O_WRITE)) {
if ((feedback_mode & EXTENDED_INFO) > 0)
{
PgmPrint("Failed to open file ");
@@ -1196,7 +1048,7 @@ void command_shell(void)
continue;
//search file in current directory and open it
- if (file.open(currentDirectory, command_arg, O_READ)) {
+ if (file.open(&currentDirectory, command_arg, O_READ)) {
Serial.print(file.fileSize());
#ifdef INCLUDE_SIMPLE_EMBEDDED
command_succedded = 1;
@@ -1233,7 +1085,7 @@ void command_shell(void)
//Print card information
cid_t cid;
- if (!card.readCID(cid)) {
+ if (!card.readCID(&cid)) {
PgmPrint("readCID failed");
continue;
}
@@ -1265,7 +1117,7 @@ void command_shell(void)
csd_t csd;
uint32_t cardSize = card.cardSize();
- if (cardSize == 0 || !card.readCSD(csd)) {
+ if (cardSize == 0 || !card.readCSD(&csd)) {
PgmPrintln("readCSD failed");
continue;
}
@@ -1302,7 +1154,7 @@ void command_shell(void)
continue;
//Try to open file, if fail (file doesn't exist), then break
- if (file.open(currentDirectory, command_arg, O_CREAT | O_EXCL | O_WRITE)) {//Will fail if file already exsists
+ if (file.open(&currentDirectory, command_arg, O_CREAT | O_EXCL | O_WRITE)) {//Will fail if file already exsists
file.close(); //Everything is good, Close this new file we just opened
#ifdef INCLUDE_SIMPLE_EMBEDDED
command_succedded = 1;
@@ -1381,7 +1233,7 @@ void command_shell(void)
file_index = 0;
PgmPrint("count|");
- Serial.println(currentDirectory.fileInfo(FI_COUNT, 0, buffer));
+ //Error Serial.println(currentDirectory.fileInfo(FI_COUNT, 0, buffer));
command_succedded = 1;
}
// efinfo <file index>
@@ -1397,7 +1249,8 @@ void command_shell(void)
{
file_index = strtolong(command_arg);
memset(buffer, 0, sizeof(buffer));
- uint32_t size = currentDirectory.fileInfo(FI_INFO, file_index, buffer);
+ //Error uint32_t size = currentDirectory.fileInfo(FI_INFO, file_index, buffer);
+ uint32_t size = 0;
Serial.print(buffer);
Serial.print('|');
Serial.println(size);
@@ -1427,19 +1280,20 @@ uint8_t read_line(char* buffer, uint8_t buffer_length)
uint8_t read_length = 0;
while(read_length < buffer_length - 1) {
- while (!Serial.available());
- uint8_t c = Serial.read();
+ //while (!Serial.available()); //We've destroyed the standard way Arduino reads characters so this no longer works
+ //uint8_t c = Serial.read();
+ uint8_t c = uart_getc(); //It would be better to pull directly from the UART buffer and use the RX interrupt, but this works
- //PORTD ^= (1<<STAT1); //Blink the stat LED while typing - this is taken care of in the UART ISR
- //PORTB ^= (1<<STAT2); //Blink the stat LED while typing - I don't want the SPI lines toggling
+ STAT1_PORT ^= (1<<STAT1); //Blink the stat LED while typing
- if(c == 0x08 || c == 0x7f) {
+ if(c == 0x08 || c == 0x7f) { //Backspace characters
if(read_length < 1)
continue;
--read_length;
buffer[read_length] = '\0';
+ //Try to erase the character sitting on the command line
Serial.print(0x08);
Serial.print(' ');
Serial.print(0x08);
@@ -1447,10 +1301,11 @@ uint8_t read_line(char* buffer, uint8_t buffer_length)
continue;
}
- Serial.print(c);
+ // Only echo back if this is enabled
+ if ((feedback_mode & ECHO) > 0)
+ Serial.print((char)c);
- //if(c == '\n')
- if(c == '\r') {
+ if(c == '\n') {
Serial.println();
buffer[read_length] = '\0';
break;
@@ -1467,6 +1322,17 @@ uint8_t read_line(char* buffer, uint8_t buffer_length)
return read_length;
}
+uint8_t uart_getc(void)
+{
+ while(!(UCSR0A & _BV(RXC0)));
+
+ uint8_t b = UDR0;
+ if(b == '\r')
+ b = '\n';
+
+ return b;
+}
+
//Reads the current system settings from EEPROM
//If anything looks weird, reset setting to default value
void read_system_settings(void)
@@ -1510,7 +1376,7 @@ void read_system_settings(void)
void print_menu(void)
{
- PgmPrintln("OpenLog v2.21");
+ PgmPrintln("OpenLog v2.3");
PgmPrintln("Available commands:");
PgmPrintln("new <file>\t\t: Creates <file>");
PgmPrintln("append <file>\t\t: Appends text to end of <file>. The text is read from the UART in a stream and is not echoed. Finish by sending Ctrl+z (ASCII 26)");
@@ -1723,8 +1589,9 @@ void system_menu(void)
{
PgmPrint("Enter a new escape character: ");
- while(!Serial.available()); //Wait for user to hit character
- setting_escape_character = Serial.read();
+ //while(!Serial.available()); //Wait for user to hit character
+ //setting_escape_character = Serial.read();
+ setting_escape_character = uart_getc();
EEPROM.write(LOCATION_ESCAPE_CHAR, setting_escape_character);
record_config_file(); //Put this new setting into the config file
@@ -1739,8 +1606,9 @@ void system_menu(void)
while(choice > 9 || choice < 1)
{
PgmPrint("\n\rEnter number of escape characters to look for (1 to 9): ");
- while(!Serial.available()); //Wait for user to hit character
- choice = Serial.read() - '0';
+ //while(!Serial.available()); //Wait for user to hit character
+ //choice = Serial.read() - '0';
+ choice = uart_getc() - '0';
}
setting_max_escape_character = choice;
@@ -1797,13 +1665,13 @@ void system_menu(void)
void read_config_file(void)
{
SdFile rootDirectory;
- if (!rootDirectory.openRoot(volume)) error("openRoot"); // open the root directory
+ if (!rootDirectory.openRoot(&volume)) error("openRoot"); // open the root directory
char configFileName[13];
sprintf(configFileName, CFG_FILENAME); //This is the name of the config file. 'config.sys' is probably a bad idea.