#include #define SINE_WAVE_ARRAY_LENGTH 26 #define BLOCK_SIZE 512 #define MAX_NUM_BLOCKS 128 // This is a limit for the number of blocks to write/read #define TEST_PIN 14 const uint8_t chipSelect = 53; // Chip select pin // Use an instance of the full SdFat library, not just SdFs, for more robust functionality if needed later. // SdFs is fine for the low-level functions used here. SdFs sd; typedef enum { BEING_FILLED, FILLED, BEING_EMPTIED, EMPTY } myBufferState_t; typedef struct { myBufferState_t state; uint8_t buffer[BLOCK_SIZE]; } sdCardBlock_t; sdCardBlock_t redBuffer, blueBuffer; // Use volatile for variables shared between ISRs and main code volatile uint8_t collectAudioData = false; // Use volatile for state variables used in both loop() and ISR volatile myBufferState_t redBufferState = BEING_FILLED; volatile myBufferState_t blueBufferState = BEING_FILLED; // Function to handle SD card errors gracefully void handleSDError(const char* msg) { Serial.println(msg); // In a real application, you might try to recover or stop sampling gracefully // For now, it just prints the error and continues the loop } void setup() { Serial.begin(9600); // Only call once pinMode(TEST_PIN, OUTPUT); // Configure ADC: A0, AVCC reference, left-justified result ADMUX = (1 << REFS0)| (1<writeStart(sdCardBlockAddress)) { handleSDError("Write start failed."); break; // Exit the case } while (!Serial.available()) { // Wait for the red buffer to be filled by the ISR while (redBufferState == // Your Code //); // Write the data to the started block if (!sd.card()->writeData(redBuffer.buffer)) { handleSDError("Write data failed."); break; // Exit the while loop } cli(); redBufferState = // Your Code //; sei(); // sdCardBlockAddress is incremented internally by writeData() or can be tracked here // Wait for the blue buffer to be filled by the ISR while (blueBufferState == // Your Code //); // Write the data to the next block if (!sd.card()->writeData(blueBuffer.buffer)) { handleSDError("Write data failed."); break; // Exit the while loop } cli(); blueBufferState = // Your Code //; sei(); // sdCardBlockAddress is incremented internally by writeData() or can be tracked here } if (!sd.card()->writeStop()) { handleSDError("Write stop failed."); } Serial.println("Sampling and logging are successful"); cli(); collectAudioData = false; sei(); while (Serial.available()) Serial.read(); // Clear serial buffer break; case 's': Serial.println("Spooling data to CSV. Press any key to stop."); Serial.println("Log to file in terminal: go to logging, select all sessions, browse and set .csv extension."); while (!Serial.available()); Serial.read(); blockCount = 0; cli(); sdCardBlockAddress = 0; sei(); // Start the read operation once if (!sd.card()->readStart(sdCardBlockAddress)) { handleSDError("Read start failed."); break; // Exit the case } while (!Serial.available() && blockCount < MAX_NUM_BLOCKS){ // Added a block limit // Read the data from the current block if (!sd.card()->readData(redBuffer.buffer)) { handleSDError("Read data failed."); break; // Exit the while loop } // sdCardBlockAddress is incremented internally by readData() for (uint16_t i = 0; i < BLOCK_SIZE; i++) { Serial.println(redBuffer.buffer[i]); } blockCount += 1; } if (!sd.card()->readStop()) { // Read stop must be called at the end handleSDError("Read stop failed."); } while (Serial.available()) Serial.read(); // Clear serial buffer break; } } } } #define RED 0 #define BLUE 1 ISR(TIMER1_COMPA_vect) { digitalWrite(TEST_PIN, HIGH); // Start the ADC conversion ADCSRA |= (1 << ADSC); digitalWrite(TEST_PIN, LOW); } ISR(ADC_vect) { static uint16_t index = 0; static uint8_t color = RED; // ADCH is volatile and safe to read uint8_t high_byte = ADCH; // Access volatile variables directly in the ISR if (collectAudioData == true) { // Use volatile state variables if ((color == RED) && (redBufferState == // Your Code //)) { redBuffer.buffer[index] = high_byte; index += 1; if (index >= BLOCK_SIZE) { redBufferState = // Your Code //; color = BLUE; index = 0; } } else if ((color == BLUE) && (blueBufferState == // Your Code //)) { blueBuffer.buffer[index] = high_byte; index += 1; if (index >= BLOCK_SIZE) { blueBufferState = // Your Code //; color = RED; index = 0; } } } else { // Reset state when not collecting data color = RED; index = 0; redBufferState = BEING_FILLED; // Ensure buffers are ready for the next run blueBufferState = BEING_FILLED; } }