virtual void flush(void) { serial_flush(); } | virtual void flush(void) { serial_flush(); } | ||||
virtual void clear(void) { serial_clear(); } | virtual void clear(void) { serial_clear(); } | ||||
virtual int availableForWrite(void) { return serial_write_buffer_free(); } | virtual int availableForWrite(void) { return serial_write_buffer_free(); } | ||||
using Print::write; | |||||
virtual size_t write(uint8_t c) { serial_putchar(c); return 1; } | virtual size_t write(uint8_t c) { serial_putchar(c); return 1; } | ||||
virtual size_t write(unsigned long n) { return write((uint8_t)n); } | virtual size_t write(unsigned long n) { return write((uint8_t)n); } | ||||
virtual size_t write(long n) { return write((uint8_t)n); } | virtual size_t write(long n) { return write((uint8_t)n); } | ||||
virtual void flush(void) { serial2_flush(); } | virtual void flush(void) { serial2_flush(); } | ||||
virtual void clear(void) { serial2_clear(); } | virtual void clear(void) { serial2_clear(); } | ||||
virtual int availableForWrite(void) { return serial2_write_buffer_free(); } | virtual int availableForWrite(void) { return serial2_write_buffer_free(); } | ||||
using Print::write; | |||||
virtual size_t write(uint8_t c) { serial2_putchar(c); return 1; } | virtual size_t write(uint8_t c) { serial2_putchar(c); return 1; } | ||||
virtual size_t write(unsigned long n) { return write((uint8_t)n); } | virtual size_t write(unsigned long n) { return write((uint8_t)n); } | ||||
virtual size_t write(long n) { return write((uint8_t)n); } | virtual size_t write(long n) { return write((uint8_t)n); } | ||||
virtual void flush(void) { serial3_flush(); } | virtual void flush(void) { serial3_flush(); } | ||||
virtual void clear(void) { serial3_clear(); } | virtual void clear(void) { serial3_clear(); } | ||||
virtual int availableForWrite(void) { return serial3_write_buffer_free(); } | virtual int availableForWrite(void) { return serial3_write_buffer_free(); } | ||||
using Print::write; | |||||
virtual size_t write(uint8_t c) { serial3_putchar(c); return 1; } | virtual size_t write(uint8_t c) { serial3_putchar(c); return 1; } | ||||
virtual size_t write(unsigned long n) { return write((uint8_t)n); } | virtual size_t write(unsigned long n) { return write((uint8_t)n); } | ||||
virtual size_t write(long n) { return write((uint8_t)n); } | virtual size_t write(long n) { return write((uint8_t)n); } | ||||
virtual void flush(void) { serial4_flush(); } | virtual void flush(void) { serial4_flush(); } | ||||
virtual void clear(void) { serial4_clear(); } | virtual void clear(void) { serial4_clear(); } | ||||
virtual int availableForWrite(void) { return serial4_write_buffer_free(); } | virtual int availableForWrite(void) { return serial4_write_buffer_free(); } | ||||
using Print::write; | |||||
virtual size_t write(uint8_t c) { serial4_putchar(c); return 1; } | virtual size_t write(uint8_t c) { serial4_putchar(c); return 1; } | ||||
virtual size_t write(unsigned long n) { return write((uint8_t)n); } | virtual size_t write(unsigned long n) { return write((uint8_t)n); } | ||||
virtual size_t write(long n) { return write((uint8_t)n); } | virtual size_t write(long n) { return write((uint8_t)n); } | ||||
virtual void flush(void) { serial5_flush(); } | virtual void flush(void) { serial5_flush(); } | ||||
virtual void clear(void) { serial5_clear(); } | virtual void clear(void) { serial5_clear(); } | ||||
virtual int availableForWrite(void) { return serial5_write_buffer_free(); } | virtual int availableForWrite(void) { return serial5_write_buffer_free(); } | ||||
using Print::write; | |||||
virtual size_t write(uint8_t c) { serial5_putchar(c); return 1; } | virtual size_t write(uint8_t c) { serial5_putchar(c); return 1; } | ||||
virtual size_t write(unsigned long n) { return write((uint8_t)n); } | virtual size_t write(unsigned long n) { return write((uint8_t)n); } | ||||
virtual size_t write(long n) { return write((uint8_t)n); } | virtual size_t write(long n) { return write((uint8_t)n); } | ||||
virtual void flush(void) { serial6_flush(); } | virtual void flush(void) { serial6_flush(); } | ||||
virtual void clear(void) { serial6_clear(); } | virtual void clear(void) { serial6_clear(); } | ||||
virtual int availableForWrite(void) { return serial6_write_buffer_free(); } | virtual int availableForWrite(void) { return serial6_write_buffer_free(); } | ||||
using Print::write; | |||||
virtual size_t write(uint8_t c) { serial6_putchar(c); return 1; } | virtual size_t write(uint8_t c) { serial6_putchar(c); return 1; } | ||||
virtual size_t write(unsigned long n) { return write((uint8_t)n); } | virtual size_t write(unsigned long n) { return write((uint8_t)n); } | ||||
virtual size_t write(long n) { return write((uint8_t)n); } | virtual size_t write(long n) { return write((uint8_t)n); } |
#define PORTA_GPCLR (*(volatile uint32_t *)0x40049080) // Global Pin Control Low Register | #define PORTA_GPCLR (*(volatile uint32_t *)0x40049080) // Global Pin Control Low Register | ||||
#define PORTA_GPCHR (*(volatile uint32_t *)0x40049084) // Global Pin Control High Register | #define PORTA_GPCHR (*(volatile uint32_t *)0x40049084) // Global Pin Control High Register | ||||
#define PORTA_ISFR (*(volatile uint32_t *)0x400490A0) // Interrupt Status Flag Register | #define PORTA_ISFR (*(volatile uint32_t *)0x400490A0) // Interrupt Status Flag Register | ||||
#define PORTA_DFER (*(volatile uint32_t *)0x400490C0) // Digital Filter Enable | |||||
#define PORTA_DFCR (*(volatile uint32_t *)0x400490C4) // Digital Filter Clock | |||||
#define PORTA_DFWR (*(volatile uint32_t *)0x400490C8) // Digital Filter Width | |||||
#define PORTB_PCR0 (*(volatile uint32_t *)0x4004A000) // Pin Control Register n | #define PORTB_PCR0 (*(volatile uint32_t *)0x4004A000) // Pin Control Register n | ||||
#define PORTB_PCR1 (*(volatile uint32_t *)0x4004A004) // Pin Control Register n | #define PORTB_PCR1 (*(volatile uint32_t *)0x4004A004) // Pin Control Register n | ||||
#define PORTB_PCR2 (*(volatile uint32_t *)0x4004A008) // Pin Control Register n | #define PORTB_PCR2 (*(volatile uint32_t *)0x4004A008) // Pin Control Register n | ||||
#define PORTB_GPCLR (*(volatile uint32_t *)0x4004A080) // Global Pin Control Low Register | #define PORTB_GPCLR (*(volatile uint32_t *)0x4004A080) // Global Pin Control Low Register | ||||
#define PORTB_GPCHR (*(volatile uint32_t *)0x4004A084) // Global Pin Control High Register | #define PORTB_GPCHR (*(volatile uint32_t *)0x4004A084) // Global Pin Control High Register | ||||
#define PORTB_ISFR (*(volatile uint32_t *)0x4004A0A0) // Interrupt Status Flag Register | #define PORTB_ISFR (*(volatile uint32_t *)0x4004A0A0) // Interrupt Status Flag Register | ||||
#define PORTB_DFER (*(volatile uint32_t *)0x4004A0C0) // Digital Filter Enable | |||||
#define PORTB_DFCR (*(volatile uint32_t *)0x4004A0C4) // Digital Filter Clock | |||||
#define PORTB_DFWR (*(volatile uint32_t *)0x4004A0C8) // Digital Filter Width | |||||
#define PORTC_PCR0 (*(volatile uint32_t *)0x4004B000) // Pin Control Register n | #define PORTC_PCR0 (*(volatile uint32_t *)0x4004B000) // Pin Control Register n | ||||
#define PORTC_PCR1 (*(volatile uint32_t *)0x4004B004) // Pin Control Register n | #define PORTC_PCR1 (*(volatile uint32_t *)0x4004B004) // Pin Control Register n | ||||
#define PORTC_PCR2 (*(volatile uint32_t *)0x4004B008) // Pin Control Register n | #define PORTC_PCR2 (*(volatile uint32_t *)0x4004B008) // Pin Control Register n | ||||
#define PORTC_GPCLR (*(volatile uint32_t *)0x4004B080) // Global Pin Control Low Register | #define PORTC_GPCLR (*(volatile uint32_t *)0x4004B080) // Global Pin Control Low Register | ||||
#define PORTC_GPCHR (*(volatile uint32_t *)0x4004B084) // Global Pin Control High Register | #define PORTC_GPCHR (*(volatile uint32_t *)0x4004B084) // Global Pin Control High Register | ||||
#define PORTC_ISFR (*(volatile uint32_t *)0x4004B0A0) // Interrupt Status Flag Register | #define PORTC_ISFR (*(volatile uint32_t *)0x4004B0A0) // Interrupt Status Flag Register | ||||
#define PORTC_DFER (*(volatile uint32_t *)0x4004B0C0) // Digital Filter Enable | |||||
#define PORTC_DFCR (*(volatile uint32_t *)0x4004B0C4) // Digital Filter Clock | |||||
#define PORTC_DFWR (*(volatile uint32_t *)0x4004B0C8) // Digital Filter Width | |||||
#define PORTD_PCR0 (*(volatile uint32_t *)0x4004C000) // Pin Control Register n | #define PORTD_PCR0 (*(volatile uint32_t *)0x4004C000) // Pin Control Register n | ||||
#define PORTD_PCR1 (*(volatile uint32_t *)0x4004C004) // Pin Control Register n | #define PORTD_PCR1 (*(volatile uint32_t *)0x4004C004) // Pin Control Register n | ||||
#define PORTD_PCR2 (*(volatile uint32_t *)0x4004C008) // Pin Control Register n | #define PORTD_PCR2 (*(volatile uint32_t *)0x4004C008) // Pin Control Register n | ||||
#define PORTD_GPCLR (*(volatile uint32_t *)0x4004C080) // Global Pin Control Low Register | #define PORTD_GPCLR (*(volatile uint32_t *)0x4004C080) // Global Pin Control Low Register | ||||
#define PORTD_GPCHR (*(volatile uint32_t *)0x4004C084) // Global Pin Control High Register | #define PORTD_GPCHR (*(volatile uint32_t *)0x4004C084) // Global Pin Control High Register | ||||
#define PORTD_ISFR (*(volatile uint32_t *)0x4004C0A0) // Interrupt Status Flag Register | #define PORTD_ISFR (*(volatile uint32_t *)0x4004C0A0) // Interrupt Status Flag Register | ||||
#define PORTD_DFER (*(volatile uint32_t *)0x4004C0C0) // Digital Filter Enable | |||||
#define PORTD_DFCR (*(volatile uint32_t *)0x4004C0C4) // Digital Filter Clock | |||||
#define PORTD_DFWR (*(volatile uint32_t *)0x4004C0C8) // Digital Filter Width | |||||
#define PORTE_PCR0 (*(volatile uint32_t *)0x4004D000) // Pin Control Register n | #define PORTE_PCR0 (*(volatile uint32_t *)0x4004D000) // Pin Control Register n | ||||
#define PORTE_PCR1 (*(volatile uint32_t *)0x4004D004) // Pin Control Register n | #define PORTE_PCR1 (*(volatile uint32_t *)0x4004D004) // Pin Control Register n | ||||
#define PORTE_PCR2 (*(volatile uint32_t *)0x4004D008) // Pin Control Register n | #define PORTE_PCR2 (*(volatile uint32_t *)0x4004D008) // Pin Control Register n | ||||
#define PORTE_GPCLR (*(volatile uint32_t *)0x4004D080) // Global Pin Control Low Register | #define PORTE_GPCLR (*(volatile uint32_t *)0x4004D080) // Global Pin Control Low Register | ||||
#define PORTE_GPCHR (*(volatile uint32_t *)0x4004D084) // Global Pin Control High Register | #define PORTE_GPCHR (*(volatile uint32_t *)0x4004D084) // Global Pin Control High Register | ||||
#define PORTE_ISFR (*(volatile uint32_t *)0x4004D0A0) // Interrupt Status Flag Register | #define PORTE_ISFR (*(volatile uint32_t *)0x4004D0A0) // Interrupt Status Flag Register | ||||
#define PORTE_DFER (*(volatile uint32_t *)0x4004D0C0) // Digital Filter Enable | |||||
#define PORTE_DFCR (*(volatile uint32_t *)0x4004D0C4) // Digital Filter Clock | |||||
#define PORTE_DFWR (*(volatile uint32_t *)0x4004D0C8) // Digital Filter Width | |||||
// System Integration Module (SIM) | // System Integration Module (SIM) | ||||
#define DAC0_DAT14L (*(volatile uint8_t *)0x400CC01C) // DAC Data Low Register | #define DAC0_DAT14L (*(volatile uint8_t *)0x400CC01C) // DAC Data Low Register | ||||
#define DAC0_DAT15L (*(volatile uint8_t *)0x400CC01E) // DAC Data Low Register | #define DAC0_DAT15L (*(volatile uint8_t *)0x400CC01E) // DAC Data Low Register | ||||
#define DAC0_SR (*(volatile uint8_t *)0x400CC020) // DAC Status Register | #define DAC0_SR (*(volatile uint8_t *)0x400CC020) // DAC Status Register | ||||
#define DAC_SR_DACBFWMF 0x04 // Buffer Watermark Flag | |||||
#define DAC_SR_DACBFRTF 0x02 // Pointer Top Position Flag | |||||
#define DAC_SR_DACBFRBF 0x01 // Pointer Bottom Position Flag | |||||
#define DAC0_C0 (*(volatile uint8_t *)0x400CC021) // DAC Control Register | #define DAC0_C0 (*(volatile uint8_t *)0x400CC021) // DAC Control Register | ||||
#define DAC_C0_DACEN 0x80 // DAC Enable | #define DAC_C0_DACEN 0x80 // DAC Enable | ||||
#define DAC_C0_DACRFS 0x40 // DAC Reference Select | #define DAC_C0_DACRFS 0x40 // DAC Reference Select | ||||
#define PDB0_CH1DLY0 (*(volatile uint32_t *)0x40036040) // Channel 1 Delay 0 Register | #define PDB0_CH1DLY0 (*(volatile uint32_t *)0x40036040) // Channel 1 Delay 0 Register | ||||
#define PDB0_CH1DLY1 (*(volatile uint32_t *)0x40036044) // Channel 1 Delay 1 Register | #define PDB0_CH1DLY1 (*(volatile uint32_t *)0x40036044) // Channel 1 Delay 1 Register | ||||
#define PDB0_DACINTC0 (*(volatile uint32_t *)0x40036150) // DAC Interval Trigger n Control Register | #define PDB0_DACINTC0 (*(volatile uint32_t *)0x40036150) // DAC Interval Trigger n Control Register | ||||
#define PDB_DACINTC_EXT 0x02 // External Trigger Input Enable | |||||
#define PDB_DACINTC_TOE 0x01 // Interval Trigger Enable | |||||
#define PDB0_DACINT0 (*(volatile uint32_t *)0x40036154) // DAC Interval n Register | #define PDB0_DACINT0 (*(volatile uint32_t *)0x40036154) // DAC Interval n Register | ||||
#define PDB0_DACINTC1 (*(volatile uint32_t *)0x40036158) // DAC Interval Trigger n Control register | #define PDB0_DACINTC1 (*(volatile uint32_t *)0x40036158) // DAC Interval Trigger n Control register | ||||
#define PDB0_DACINT1 (*(volatile uint32_t *)0x4003615C) // DAC Interval n register | #define PDB0_DACINT1 (*(volatile uint32_t *)0x4003615C) // DAC Interval n register |
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) | #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) | ||||
#if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) | #if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) | ||||
/* | |||||
* Let __ARM_FEATURE_UNALIGNED be set by the achitechture and the compiler flags: | |||||
* -munaligned-access | |||||
* -mno-unaligned-access | |||||
* instead of always setting it here. | |||||
* | |||||
#define __ARM_FEATURE_UNALIGNED 1 | #define __ARM_FEATURE_UNALIGNED 1 | ||||
*/ | |||||
/* This memcpy routine is optimised for Cortex-M3/M4 cores with/without | /* This memcpy routine is optimised for Cortex-M3/M4 cores with/without | ||||
unaligned access. | unaligned access. |
#include "kinetis.h" | #include "kinetis.h" | ||||
#include "core_pins.h" // testing only | #include "core_pins.h" // testing only | ||||
#include "ser_print.h" // testing only | #include "ser_print.h" // testing only | ||||
#include <errno.h> | |||||
// Flash Security Setting. On Teensy 3.2, you can lock the MK20 chip to prevent | // Flash Security Setting. On Teensy 3.2, you can lock the MK20 chip to prevent | ||||
char *__brkval = (char *)&_ebss; | char *__brkval = (char *)&_ebss; | ||||
#ifndef STACK_MARGIN | |||||
#if defined(__MKL26Z64__) | |||||
#define STACK_MARGIN 512 | |||||
#elif defined(__MK20DX128__) | |||||
#define STACK_MARGIN 1024 | |||||
#elif defined(__MK20DX256__) | |||||
#define STACK_MARGIN 4096 | |||||
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||||
#define STACK_MARGIN 8192 | |||||
#endif | |||||
#endif | |||||
void * _sbrk(int incr) | void * _sbrk(int incr) | ||||
{ | { | ||||
char *prev = __brkval; | |||||
__brkval += incr; | |||||
char *prev, *stack; | |||||
prev = __brkval; | |||||
if (incr != 0) { | |||||
__asm__ volatile("mov %0, sp" : "=r" (stack) ::); | |||||
if (prev + incr >= stack - STACK_MARGIN) { | |||||
errno = ENOMEM; | |||||
return (void *)-1; | |||||
} | |||||
__brkval = prev + incr; | |||||
} | |||||
return prev; | return prev; | ||||
} | } | ||||
if (SMC_PMSTAT == SMC_PMSTAT_RUN) { | if (SMC_PMSTAT == SMC_PMSTAT_RUN) { | ||||
// Turn HSRUN mode on | // Turn HSRUN mode on | ||||
SMC_PMCTRL = SMC_PMCTRL_RUNM(3); | SMC_PMCTRL = SMC_PMCTRL_RUNM(3); | ||||
while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) ; // wait | |||||
while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) {;} // wait | |||||
// Then configure clock for full speed | // Then configure clock for full speed | ||||
#if F_CPU == 240000000 && F_BUS == 60000000 | #if F_CPU == 240000000 && F_BUS == 60000000 | ||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7); | SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7); |
} | } | ||||
s = fcvtf(val, precision, &decpt, &sign); | s = fcvtf(val, precision, &decpt, &sign); | ||||
// if only 1 digit in output | |||||
if (precision == 0 && decpt == 0) { | if (precision == 0 && decpt == 0) { | ||||
// round and move decimal point | |||||
s = (*s < '5') ? "0" : "1"; | s = (*s < '5') ? "0" : "1"; | ||||
reqd = 1; | |||||
} else { | |||||
reqd = strlen(s); | |||||
if (reqd > decpt) reqd++; | |||||
if (decpt == 0) reqd++; | |||||
decpt++; | |||||
} | |||||
// if all zeros, limit to precision | |||||
if (-decpt > (int)precision) { | |||||
s = "0"; | |||||
decpt = -precision; | |||||
} | |||||
reqd = strlen(s); | |||||
// add 1 for decimal point | |||||
if (reqd > decpt) reqd++; | |||||
// add 1 for zero in front of decimal point | |||||
if (decpt == 0) reqd++; | |||||
// if leading zeros after decimal point | |||||
if (decpt < 0 && precision > 0) { | |||||
// ensure enough trailing zeros, add 2 for '0.' | |||||
reqd = precision + 2; | |||||
if (strlen(s) > precision + decpt) { | |||||
// bug in fcvtf. e.g. 0.012, precision 2 should return 1 instead of 12. | |||||
// However, 1.2, precision 0 returns correct value. So shift values so | |||||
// that decimal point is after the first digit, then convert again | |||||
int newPrecision = precision; | |||||
int newDecimalPoint; | |||||
// shift decimal point | |||||
while (newPrecision > 0) { | |||||
val *= 10.0; | |||||
newPrecision--; | |||||
} | |||||
// round after accounting for leading 0's | |||||
s = fcvtf(val, newPrecision, &newDecimalPoint, &sign); | |||||
// if rounded up to new digit (e.g. 0.09 to 0.1), move decimal point | |||||
if (newDecimalPoint - decpt == precision + 1) decpt++; | |||||
} | |||||
} | } | ||||
// add 1 for sign if negative | |||||
if (sign) reqd++; | if (sign) reqd++; | ||||
p = buf; | p = buf; | ||||
e = p + reqd; | e = p + reqd; | ||||
pad = width - reqd; | pad = width - reqd; | ||||
else if (decpt < 0 && precision > 0) { | else if (decpt < 0 && precision > 0) { | ||||
*p++ = '0'; | *p++ = '0'; | ||||
*p++ = '.'; | *p++ = '.'; | ||||
e++; | |||||
// print leading zeros | |||||
while ( decpt < 0 ) { | while ( decpt < 0 ) { | ||||
decpt++; | decpt++; | ||||
*p++ = '0'; | *p++ = '0'; | ||||
} | } | ||||
} | } | ||||
// print digits | |||||
while (p < e) { | while (p < e) { | ||||
*p++ = *s++; | *p++ = *s++; | ||||
if (p == e) break; | if (p == e) break; |
// for background about this startup delay, please see these conversations | // for background about this startup delay, please see these conversations | ||||
// https://forum.pjrc.com/threads/36606-startup-time-(400ms)?p=113980&viewfull=1#post113980 | // https://forum.pjrc.com/threads/36606-startup-time-(400ms)?p=113980&viewfull=1#post113980 | ||||
// https://forum.pjrc.com/threads/31290-Teensey-3-2-Teensey-Loader-1-24-Issues?p=87273&viewfull=1#post87273 | // https://forum.pjrc.com/threads/31290-Teensey-3-2-Teensey-Loader-1-24-Issues?p=87273&viewfull=1#post87273 | ||||
delay(400); | |||||
delay(50); | |||||
usb_init(); | usb_init(); | ||||
delay(350); | |||||
} | } | ||||
ftmClock = 16000000; | ftmClock = 16000000; | ||||
} else | } else | ||||
#endif | #endif | ||||
#if defined(__MKL26Z64__) | |||||
// Teensy LC does not support slow clock source (ftmClockSource = 2) | |||||
ftmClockSource = 1; // Use default F_TIMER clock source | |||||
ftmClock = F_TIMER; // Set variable for the actual timer clock frequency | |||||
#else | |||||
if (frequency < (float)(F_TIMER >> 7) / 65536.0f) { | if (frequency < (float)(F_TIMER >> 7) / 65536.0f) { | ||||
// frequency is too low for working with F_TIMER: | // frequency is too low for working with F_TIMER: | ||||
ftmClockSource = 2; // Use alternative 31250Hz clock source | ftmClockSource = 2; // Use alternative 31250Hz clock source | ||||
ftmClockSource = 1; // Use default F_TIMER clock source | ftmClockSource = 1; // Use default F_TIMER clock source | ||||
ftmClock = F_TIMER; // Set variable for the actual timer clock frequency | ftmClock = F_TIMER; // Set variable for the actual timer clock frequency | ||||
} | } | ||||
#endif | |||||
for (prescale = 0; prescale < 7; prescale++) { | for (prescale = 0; prescale < 7; prescale++) { |
case 21: CORE_PIN21_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break; | case 21: CORE_PIN21_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break; | ||||
#if defined(KINETISL) | #if defined(KINETISL) | ||||
case 3: CORE_PIN3_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); break; | case 3: CORE_PIN3_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); break; | ||||
case 25: CORE_PIN25_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(4); break; | |||||
#endif | #endif | ||||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) | #if defined(__MK64FX512__) || defined(__MK66FX1M0__) | ||||
case 27: CORE_PIN27_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break; | case 27: CORE_PIN27_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break; | ||||
case 5: CORE_PIN5_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break; | case 5: CORE_PIN5_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break; | ||||
#if defined(KINETISL) | #if defined(KINETISL) | ||||
case 4: CORE_PIN4_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); break; | case 4: CORE_PIN4_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); break; | ||||
case 24: CORE_PIN24_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(4); break; | |||||
#endif | #endif | ||||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) | #if defined(__MK64FX512__) || defined(__MK66FX1M0__) | ||||
case 26: CORE_PIN26_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break; | case 26: CORE_PIN26_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break; | ||||
while (transmitting) yield(); // wait for buffered data to send | while (transmitting) yield(); // wait for buffered data to send | ||||
NVIC_DISABLE_IRQ(IRQ_UART0_STATUS); | NVIC_DISABLE_IRQ(IRQ_UART0_STATUS); | ||||
UART0_C2 = 0; | UART0_C2 = 0; | ||||
CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); | |||||
CORE_PIN1_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); | |||||
switch (rx_pin_num) { | |||||
case 0: CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
case 21: CORE_PIN21_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
#if defined(KINETISL) | |||||
case 3: CORE_PIN3_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
case 25: CORE_PIN25_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
#endif | |||||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||||
case 27: CORE_PIN27_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
#endif | |||||
} | |||||
switch (tx_pin_num & 127) { | |||||
case 1: CORE_PIN1_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
case 5: CORE_PIN5_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
#if defined(KINETISL) | |||||
case 4: CORE_PIN4_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
case 24: CORE_PIN24_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
#endif | |||||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||||
case 26: CORE_PIN26_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
#endif | |||||
} | |||||
rx_buffer_head = 0; | rx_buffer_head = 0; | ||||
rx_buffer_tail = 0; | rx_buffer_tail = 0; | ||||
if (rts_pin) rts_deassert(); | if (rts_pin) rts_deassert(); | ||||
} | } | ||||
#else | #else | ||||
if (UART0_S1 & UART_S1_RDRF) { | if (UART0_S1 & UART_S1_RDRF) { | ||||
n = UART0_D; | |||||
if (use9Bits && (UART0_C3 & 0x80)) n |= 0x100; | |||||
if (use9Bits && (UART0_C3 & 0x80)) { | |||||
n = UART0_D | 0x100; | |||||
} else { | |||||
n = UART0_D; | |||||
} | |||||
head = rx_buffer_head + 1; | head = rx_buffer_head + 1; | ||||
if (head >= SERIAL1_RX_BUFFER_SIZE) head = 0; | if (head >= SERIAL1_RX_BUFFER_SIZE) head = 0; | ||||
if (head != rx_buffer_tail) { | if (head != rx_buffer_tail) { |
} | } | ||||
#else | #else | ||||
if (UART1_S1 & UART_S1_RDRF) { | if (UART1_S1 & UART_S1_RDRF) { | ||||
n = UART1_D; | |||||
if (use9Bits && (UART1_C3 & 0x80)) n |= 0x100; | |||||
if (use9Bits && (UART1_C3 & 0x80)) { | |||||
n = UART1_D | 0x100; | |||||
} else { | |||||
n = UART1_D; | |||||
} | |||||
head = rx_buffer_head + 1; | head = rx_buffer_head + 1; | ||||
if (head >= SERIAL2_RX_BUFFER_SIZE) head = 0; | if (head >= SERIAL2_RX_BUFFER_SIZE) head = 0; | ||||
if (head != rx_buffer_tail) { | if (head != rx_buffer_tail) { |
while (transmitting) yield(); // wait for buffered data to send | while (transmitting) yield(); // wait for buffered data to send | ||||
NVIC_DISABLE_IRQ(IRQ_UART2_STATUS); | NVIC_DISABLE_IRQ(IRQ_UART2_STATUS); | ||||
UART2_C2 = 0; | UART2_C2 = 0; | ||||
#if defined(KINETISK) | |||||
CORE_PIN7_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); | CORE_PIN7_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); | ||||
CORE_PIN8_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); | CORE_PIN8_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); | ||||
#elif defined(KINETISL) | |||||
switch (rx_pin_num) { | |||||
case 7: CORE_PIN7_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
case 6: CORE_PIN6_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
} | |||||
switch (tx_pin_num & 127) { | |||||
case 8: CORE_PIN8_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
case 20: CORE_PIN20_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; | |||||
} | |||||
#endif | |||||
rx_buffer_head = 0; | rx_buffer_head = 0; | ||||
rx_buffer_tail = 0; | rx_buffer_tail = 0; | ||||
if (rts_pin) rts_deassert(); | if (rts_pin) rts_deassert(); |
while (transmitting) yield(); // wait for buffered data to send | while (transmitting) yield(); // wait for buffered data to send | ||||
NVIC_DISABLE_IRQ(IRQ_UART3_STATUS); | NVIC_DISABLE_IRQ(IRQ_UART3_STATUS); | ||||
UART3_C2 = 0; | UART3_C2 = 0; | ||||
CORE_PIN31_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); | |||||
CORE_PIN32_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); | |||||
switch (rx_pin_num) { | switch (rx_pin_num) { | ||||
case 31: CORE_PIN31_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTC3 | case 31: CORE_PIN31_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTC3 | ||||
case 63: CORE_PIN63_CONFIG = 0; break; | case 63: CORE_PIN63_CONFIG = 0; break; |
uint16_t AudioInputUSB::incoming_count; | uint16_t AudioInputUSB::incoming_count; | ||||
uint8_t AudioInputUSB::receive_flag; | uint8_t AudioInputUSB::receive_flag; | ||||
struct usb_audio_features_struct AudioInputUSB::features = {0,0,FEATURE_MAX_VOLUME}; | |||||
struct usb_audio_features_struct AudioInputUSB::features = {0,0,FEATURE_MAX_VOLUME/2}; | |||||
#define DMABUFATTR __attribute__ ((section(".dmabuffers"), aligned (4))) | #define DMABUFATTR __attribute__ ((section(".dmabuffers"), aligned (4))) | ||||
uint16_t usb_audio_receive_buffer[AUDIO_RX_SIZE/2] DMABUFATTR; | uint16_t usb_audio_receive_buffer[AUDIO_RX_SIZE/2] DMABUFATTR; | ||||
return target * 4; | return target * 4; | ||||
} | } | ||||
struct setup_struct { | |||||
union { | |||||
struct { | |||||
uint8_t bmRequestType; | |||||
uint8_t bRequest; | |||||
union { | |||||
struct { | |||||
uint8_t bChannel; // 0=main, 1=left, 2=right | |||||
uint8_t bCS; // Control Selector | |||||
}; | |||||
uint16_t wValue; | |||||
}; | |||||
union { | |||||
struct { | |||||
uint8_t bIfEp; // type of entity | |||||
uint8_t bEntityId; // UnitID, TerminalID, etc. | |||||
}; | |||||
uint16_t wIndex; | |||||
}; | |||||
uint16_t wLength; | |||||
}; | |||||
}; | |||||
}; | |||||
int usb_audio_get_feature(void *stp, uint8_t *data, uint32_t *datalen) | int usb_audio_get_feature(void *stp, uint8_t *data, uint32_t *datalen) | ||||
{ | { | ||||
struct setup_struct setup = *((struct setup_struct *)stp); | struct setup_struct setup = *((struct setup_struct *)stp); |
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
// setup struct definition could be moved from usb_dev.c to usb_dev.h so we can reuse | |||||
// it instead of redefining it here | |||||
struct setup_struct { | |||||
union { | |||||
struct { | |||||
uint8_t bmRequestType; | |||||
uint8_t bRequest; | |||||
union { | |||||
struct { | |||||
uint8_t bChannel; // 0=main, 1=left, 2=right | |||||
uint8_t bCS; // Control Selector | |||||
}; | |||||
uint16_t wValue; | |||||
}; | |||||
union { | |||||
struct { | |||||
uint8_t bIfEp; // type of entity | |||||
uint8_t bEntityId; // UnitID, TerminalID, etc. | |||||
}; | |||||
uint16_t wIndex; | |||||
}; | |||||
uint16_t wLength; | |||||
}; | |||||
}; | |||||
}; | |||||
// audio features supported | // audio features supported | ||||
struct usb_audio_features_struct { | struct usb_audio_features_struct { | ||||
int change; // set to 1 when any value is changed | int change; // set to 1 when any value is changed | ||||
friend void usb_audio_receive_callback(unsigned int len); | friend void usb_audio_receive_callback(unsigned int len); | ||||
friend int usb_audio_set_feature(void *stp, uint8_t *buf); | friend int usb_audio_set_feature(void *stp, uint8_t *buf); | ||||
friend int usb_audio_get_feature(void *stp, uint8_t *data, uint32_t *datalen); | friend int usb_audio_get_feature(void *stp, uint8_t *data, uint32_t *datalen); | ||||
static struct usb_audio_features_struct features; | static struct usb_audio_features_struct features; | ||||
float volume(void) { | |||||
if (features.mute) return 0.0; | |||||
return (float)(features.volume) * (1.0 / (float)FEATURE_MAX_VOLUME); | |||||
} | |||||
private: | private: | ||||
static bool update_responsibility; | static bool update_responsibility; | ||||
static audio_block_t *incoming_left; | static audio_block_t *incoming_left; |
9, // bLength | 9, // bLength | ||||
5, // bDescriptorType, 5 = ENDPOINT_DESCRIPTOR | 5, // bDescriptorType, 5 = ENDPOINT_DESCRIPTOR | ||||
AUDIO_TX_ENDPOINT | 0x80, // bEndpointAddress | AUDIO_TX_ENDPOINT | 0x80, // bEndpointAddress | ||||
0x05, // bmAttributes = isochronous, asynchronous | |||||
0x09, // bmAttributes = isochronous, adaptive | |||||
LSB(AUDIO_TX_SIZE), MSB(AUDIO_TX_SIZE), // wMaxPacketSize | LSB(AUDIO_TX_SIZE), MSB(AUDIO_TX_SIZE), // wMaxPacketSize | ||||
1, // bInterval, 1 = every frame | 1, // bInterval, 1 = every frame | ||||
0, // bRefresh | 0, // bRefresh |
class usb_serial_class : public Stream | class usb_serial_class : public Stream | ||||
{ | { | ||||
public: | public: | ||||
void begin(long) { /* TODO: call a function that tries to wait for enumeration */ }; | |||||
void begin(long) { | |||||
uint32_t millis_begin = systick_millis_count; | |||||
while (!(*this)) { | |||||
// wait up to 1 second for Arduino Serial Monitor | |||||
if ((uint32_t)(systick_millis_count - millis_begin) > 1000) break; | |||||
} | |||||
} | |||||
void end() { /* TODO: flush output and shut down USB port */ }; | void end() { /* TODO: flush output and shut down USB port */ }; | ||||
virtual int available() { return usb_serial_available(); } | virtual int available() { return usb_serial_available(); } | ||||
virtual int read() { return usb_serial_getchar(); } | virtual int read() { return usb_serial_getchar(); } |