/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


//
// Please refer to "3rd_party/docs/schematic/DMA_WaveOut_LPF.png" for the LPF circuit
//


#include <eCxx/eCxx.h>

#include "NodeMCU_Common.h"


//
// Sample data
//

// This LUT is copied (with some reformatting) from:
//     https://www.hackster.io/janost/audio-hacking-on-the-esp8266-fa9464
//
// NOTE : It should produce a sine wave at ~172 Hz
static eCxx::uint16_t sineLUT[256] = {
    0x8000, 0x8324, 0x8647, 0x896A, 0x8C8B, 0x8FAB, 0x92C8, 0x95E2, 0x98F8, 0x9C0B, 0x9F19, 0xA223, 0xA528, 0xA826, 0xAB1F, 0xAE11,
    0xB0FB, 0xB3DE, 0xB6BA, 0xB98C, 0xBC56, 0xBF17, 0xC1CE, 0xC47A, 0xC71C, 0xC9B4, 0xCC3F, 0xCEBF, 0xD133, 0xD39B, 0xD5F5, 0xD842,
    0xDA82, 0xDCB4, 0xDED7, 0xE0EC, 0xE2F2, 0xE4E8, 0xE6CF, 0xE8A6, 0xEA6D, 0xEC24, 0xEDCA, 0xEF5F, 0xF0E2, 0xF255, 0xF3B5, 0xF504,
    0xF641, 0xF76C, 0xF884, 0xF98A, 0xFA7D, 0xFB5D, 0xFC29, 0xFCE3, 0xFD8A, 0xFE1D, 0xFE9D, 0xFF09, 0xFF62, 0xFFA7, 0xFFD8, 0xFFF6,
    0xFFFF, 0xFFF6, 0xFFD8, 0xFFA7, 0xFF62, 0xFF09, 0xFE9D, 0xFE1D, 0xFD8A, 0xFCE3, 0xFC29, 0xFB5D, 0xFA7D, 0xF98A, 0xF884, 0xF76C,
    0xF641, 0xF504, 0xF3B5, 0xF255, 0xF0E2, 0xEF5F, 0xEDCA, 0xEC24, 0xEA6D, 0xE8A6, 0xE6CF, 0xE4E8, 0xE2F2, 0xE0EC, 0xDED7, 0xDCB4,
    0xDA82, 0xD842, 0xD5F5, 0xD39B, 0xD133, 0xCEBF, 0xCC3F, 0xC9B4, 0xC71C, 0xC47A, 0xC1CE, 0xBF17, 0xBC56, 0xB98C, 0xB6BA, 0xB3DE,
    0xB0FB, 0xAE11, 0xAB1F, 0xA826, 0xA528, 0xA223, 0x9F19, 0x9C0B, 0x98F8, 0x95E2, 0x92C8, 0x8FAB, 0x8C8B, 0x896A, 0x8647, 0x8324,
    0x8000, 0x7CDC, 0x79B9, 0x7696, 0x7375, 0x7055, 0x6D38, 0x6A1E, 0x6708, 0x63F5, 0x60E7, 0x5DDD, 0x5AD8, 0x57DA, 0x54E1, 0x51EF,
    0x4F05, 0x4C22, 0x4946, 0x4674, 0x43AA, 0x40E9, 0x3E32, 0x3B86, 0x38E4, 0x364C, 0x33C1, 0x3141, 0x2ECD, 0x2C65, 0x2A0B, 0x27BE,
    0x257E, 0x234C, 0x2129, 0x1F14, 0x1D0E, 0x1B18, 0x1931, 0x175A, 0x1593, 0x13DC, 0x1236, 0x10A1, 0x0F1E, 0x0DAB, 0x0C4B, 0x0AFC,
    0x09BF, 0x0894, 0x077C, 0x0676, 0x0583, 0x04A3, 0x03D7, 0x031D, 0x0276, 0x01E3, 0x0163, 0x00F7, 0x009E, 0x0059, 0x0028, 0x000A,
    0x0000, 0x000A, 0x0028, 0x0059, 0x009E, 0x00F7, 0x0163, 0x01E3, 0x0276, 0x031D, 0x03D7, 0x04A3, 0x0583, 0x0676, 0x077C, 0x0894,
    0x09BF, 0x0AFC, 0x0C4B, 0x0DAB, 0x0F1E, 0x10A1, 0x1236, 0x13DC, 0x1593, 0x175A, 0x1931, 0x1B18, 0x1D0E, 0x1F14, 0x2129, 0x234C,
    0x257E, 0x27BE, 0x2A0B, 0x2C65, 0x2ECD, 0x3141, 0x33C1, 0x364C, 0x38E4, 0x3B86, 0x3E32, 0x40E9, 0x43AA, 0x4674, 0x4946, 0x4C22,
    0x4F05, 0x51EF, 0x54E1, 0x57DA, 0x5AD8, 0x5DDD, 0x60E7, 0x63F5, 0x6708, 0x6A1E, 0x6D38, 0x7055, 0x7375, 0x7696, 0x79B9, 0x7CDC
};


//
// Include common source code for DMA*WaveOut test application
//
#include "DMAWaveOut_Common.h"


//
// The init function
//
void eCxx_user_init() __ECXX_ATTR_OPTIMIZE_2;
void eCxx_user_init()
{
    // Initialize application
    initBasicNodeMCUApp();

    // Enable the 74LVC541 buffers on the eCxx NodeMCU development board because
    // the I2S_DATA pin is buffered
    App::setPinMode  ( eCxx::NodeMCU::D0, eCxx::Application::PinMode::Output ); // GPIO16
    App::digitalWrite( eCxx::NodeMCU::D0, false                              ); // The buffers are active low

    // Initialize I2SOut
    App::i2sOut().begin(
        44100,
        +[]() ICACHE_RAM_ATTR {
            // NOTE : Do not disable interrupt here or the system will hung and restart!
            for(eCxx::uint32_t p = 0; p < eCxx::arraySize(sineLUT); ++p) {
                writeSample(sineLUT[p]);
            }
        },
        0,     // Use the default buffer length
        false, // Disable I2S_BCK pin
        false  // Disable I2S_WS  pin
    );
}


//
// The task function
//
void eCxx_user_task()
{
#if 0

    // Process event
    eCxx::Application::processEvent();

#else

    // Process event and delay
    static eCxx::uint32_t prvMillis = 0;
           eCxx::uint32_t curMillis = App::processEvent();
    if(curMillis - prvMillis < 1000 * 5 / 172 ) return;
    else                                        prvMillis = curMillis;

    // Pause and resume every ~5 waveforms
    static bool pause = false;
    pause = !pause;

    if(pause) App::i2sOut().pause ();
    else      App::i2sOut().resume();

#endif
}
