#include "resource_table.h"         /*!< Resourcetable for SK_AM64 needed to tell the PRU which resources are used */
#include "intc_map_0.h"

// different cores use different outpins for debugging
#ifdef PRU0
    #define DEBUG_PIN_SHIFT_B 4     // D2 
    #define DEBUG_PIN_SHIFT_C 11    // D4
#else
    #define DEBUG_PIN_SHIFT_B 12    // D3
    #define DEBUG_PIN_SHIFT_C 9     // D5
#endif

#define SPINLOCK_DEV 0x90                       /*!< PRU XFR Device für Spinlocks */
#define SPINLOCK_BASE_REGISTER 1                /*!< Base register to use */
#define SPINLOCK_USE_REMAPPING 0                /*!< We do not use remapping */
#define SPINLOCK_ID_COUNT 64                    /*!< How many spinlocks are possible */
#define SPINLOCK_ID_MASK SPINLOCK_ID_COUNT - 1  /*!< Mask, for sanity checks of spinlock id */

#define SPINLOCK_ID 11  // any Id: just for testing

volatile register uint32_t __R30;

// define what version of spinlock_acquire we use (asm or C)
// #define USE_ASM

#ifdef USE_ASM
extern void spinlock_acquire(uint8_t lock_id);
extern void spinlock_release(uint8_t lock_id);
#else
static inline void spinlock_acquire(uint8_t lock_id)
{
    uint32_t obj = lock_id & SPINLOCK_ID_MASK;
    do {
        __xin(SPINLOCK_DEV, SPINLOCK_BASE_REGISTER, SPINLOCK_USE_REMAPPING, obj);
        if (((obj >> 24) & 0x01) == 1)
        {
            /* acquired */
            return;
        }
        __R30 ^= (1 << DEBUG_PIN_SHIFT_C);
        /* not acquired */
    } while (1);
}

static inline void spinlock_release(uint8_t lock_id)
{
    uint32_t obj = (lock_id & SPINLOCK_ID_MASK) << 24;   // <- IMPORTANT LINE
    __xout(SPINLOCK_DEV, SPINLOCK_BASE_REGISTER, SPINLOCK_USE_REMAPPING, obj);
}
#endif

int main()
{
    while(1) {
        spinlock_acquire(SPINLOCK_ID);

        __R30 |= (1 << DEBUG_PIN_SHIFT_B);

        //different delay for each core
        #if PRU0
        __delay_cycles(1000);
        #else
        __delay_cycles(300);
        #endif
        __R30 &= ~(1 << DEBUG_PIN_SHIFT_B);

        spinlock_release(SPINLOCK_ID);
        // __delay_cycles(300);
        
    }
}

