From d396e85fe022287cc81f8428004ce960b1e4e6b2 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 5 Dec 2013 11:06:58 +0100 Subject: [PATCH] 9XR-PRO support. Still not finished. --- radio/src/Makefile | 28 +-- radio/src/gui/menu_general.cpp | 2 +- radio/src/gui/view_statistics.cpp | 2 +- radio/src/opentx.cpp | 2 +- radio/src/targets/sky9x/audio_driver.cpp | 17 +- radio/src/targets/sky9x/board_sky9x.cpp | 8 +- radio/src/targets/sky9x/board_sky9x.h | 5 +- radio/src/targets/sky9x/coproc_driver.cpp | 55 ++---- radio/src/targets/sky9x/lcd_driver.cpp | 44 +++-- radio/src/targets/sky9x/rtc_driver.cpp | 201 ++++++++++++++++++++++ 10 files changed, 279 insertions(+), 85 deletions(-) diff --git a/radio/src/Makefile b/radio/src/Makefile index 73515c551..7ffe21961 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -50,7 +50,7 @@ DELAY = 5 #----------- BUILD OPTIONS --------------------------- # PCB version -# Values: 9X, 9X128, 9X2561, 9XR, 9XR128, 9XR2561, GRUVIN9X, MEGA2560, SKY9X, TARANIS +# Values: 9X, 9X128, 9X2561, 9XR, 9XR128, 9XR2561, GRUVIN9X, MEGA2560, SKY9X, 9XRPRO, TARANIS # Old values STD and STD128 are mapped to 9X and 9X128 for compatibility PCB = 9X @@ -264,7 +264,7 @@ INCDIRS = . translations EXTRAINCDIRS = # MCU name -ifneq ($(PCB), $(filter $(PCB), STD 9X 9XR STD128 9X128 9XR128 9X2561 9XR2561 GRUVIN9X MEGA2560 SKY9X TARANIS)) +ifneq ($(PCB), $(filter $(PCB), STD 9X 9XR STD128 9X128 9XR128 9X2561 9XR2561 GRUVIN9X MEGA2560 SKY9X 9XRPRO TARANIS)) $(error Sorry, the PCB $(PCB) is not supported yet in openTx) endif @@ -520,19 +520,25 @@ ifeq ($(PCB), MEGA2560) CPPDEFS += -DROTARY_ENCODERS=${ROTARY_ENCODERS} endif -ifeq ($(PCB), SKY9X) - # 9x radio with a sky9x replacement board +ifeq ($(PCB), $(filter $(PCB), SKY9X 9XRPRO)) + # 9x/9XR radio with a sky9x replacement board ARCH = ARM - CPPDEFS = -Dat91sam3s4 - ifeq ($(PCBREV), REVA) + CPPDEFS = -Dat91sam3s4 + ifeq ($(PCB), 9XRPRO) + CPPDEFS += -DREVX + LDSCRIPT = targets/sky9x/sam3s4c_flash.ld + else ifeq ($(PCBREV), REVA) CPPDEFS += -DREVA LDSCRIPT = targets/sky9x/sam3s2c_flash.ld + CPPSRC += targets/sky9x/coproc_driver.cpp else ifeq ($(PCBREV), REVB) - CPPDEFS += -DREVB + CPPDEFS += -DREVB -DCOPROCESSOR LDSCRIPT = targets/sky9x/sam3s4c_flash.ld + CPPSRC += targets/sky9x/coproc_driver.cpp else - CPPDEFS += -DREVC + CPPDEFS += -DREVC -DCOPROCESSOR LDSCRIPT = targets/sky9x/sam3s4c_flash.ld + CPPSRC += targets/sky9x/coproc_driver.cpp endif TRGT = arm-none-eabi- MCU = cortex-m3 @@ -553,7 +559,7 @@ ifeq ($(PCB), SKY9X) EEPROMSRC = eeprom_common.cpp eeprom_raw.cpp eeprom_conversions.cpp PULSESSRC = protocols/pulses_arm.cpp protocols/ppm_arm.cpp protocols/pxx_arm.cpp protocols/dsm2_arm.cpp CPPSRC += audio_arm.cpp haptic.cpp gui/view_about.cpp - CPPSRC += targets/sky9x/pwr_driver.cpp targets/sky9x/adc_driver.cpp targets/sky9x/coproc_driver.cpp targets/sky9x/rotenc_driver.cpp targets/sky9x/eeprom_driver.cpp targets/sky9x/pulses_driver.cpp targets/sky9x/keys_driver.cpp targets/sky9x/audio_driver.cpp targets/sky9x/buzzer_driver.cpp targets/sky9x/haptic_driver.cpp targets/sky9x/sdcard_driver.cpp targets/sky9x/massstorage.cpp + CPPSRC += targets/sky9x/pwr_driver.cpp targets/sky9x/adc_driver.cpp targets/sky9x/rotenc_driver.cpp targets/sky9x/eeprom_driver.cpp targets/sky9x/pulses_driver.cpp targets/sky9x/keys_driver.cpp targets/sky9x/audio_driver.cpp targets/sky9x/buzzer_driver.cpp targets/sky9x/haptic_driver.cpp targets/sky9x/sdcard_driver.cpp targets/sky9x/massstorage.cpp ifeq ($(SDCARD), YES) CPPDEFS += -DVOICE @@ -687,8 +693,8 @@ FORMAT = ihex TARGET = opentx # List C++ source files here. (C dependencies are automatically generated.) -ifeq ($(PCB), $(filter $(PCB), SKY9X TARANIS)) - TTS_SRC = translations/tts_cz.cpp translations/tts_de.cpp translations/tts_en.cpp translations/tts_es.cpp translations/tts_fr.cpp translations/tts_it.cpp translations/tts_pl.cpp translations/tts_pt.cpp translations/tts_sk.cpp translations/tts_se.cpp +ifeq ($(PCB), $(filter $(PCB), SKY9X 9XRPRO TARANIS)) + TTS_SRC = translations/tts_cz.cpp translations/tts_de.cpp translations/tts_en.cpp translations/tts_es.cpp translations/tts_fr.cpp translations/tts_it.cpp translations/tts_pt.cpp translations/tts_sk.cpp translations/tts_se.cpp else STD_TTS_SRC = translations/tts_$(shell sh -c "echo $(TTS) | tr '[:upper:]' '[:lower:]'").cpp TTS_SRC = $(shell sh -c "if test -f $(STD_TTS_SRC); then echo $(STD_TTS_SRC); else echo translations/tts_en.cpp; fi") diff --git a/radio/src/gui/menu_general.cpp b/radio/src/gui/menu_general.cpp index e6b7956ca..f2d2c2353 100644 --- a/radio/src/gui/menu_general.cpp +++ b/radio/src/gui/menu_general.cpp @@ -1040,7 +1040,7 @@ void menuGeneralVersion(uint8_t event) lcd_putsLeft(2*FH, stamp1); lcd_putsLeft(3*FH, stamp2); lcd_putsLeft(4*FH, stamp3); -#if defined(PCBSKY9X) && !defined(REVA) +#if defined(COPROCESSOR) if (Coproc_valid == 1) { lcd_putsLeft(5*FH, PSTR("CoPr:")); lcd_outdez8(10*FW, 5*FH, Coproc_read); diff --git a/radio/src/gui/view_statistics.cpp b/radio/src/gui/view_statistics.cpp index b352b85da..082f19df8 100644 --- a/radio/src/gui/view_statistics.cpp +++ b/radio/src/gui/view_statistics.cpp @@ -158,7 +158,7 @@ void menuStatisticsDebug(uint8_t event) putsTelemetryValue(20*FW+2, 3*FH, maxTemperature+g_eeGeneral.temperatureCalib, UNIT_DEGREES, 0); #endif -#if defined(PCBSKY9X) +#if defined(COPROCESSOR) lcd_putsLeft(4*FH, STR_COPROC_TEMP); if (Coproc_read==0) { diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index d1612ec1d..926eba440 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -316,7 +316,7 @@ void per10ms() /* Update global Date/Time every 100 per10ms cycles */ if (++g_ms100 == 100) { g_rtcTime++; // inc global unix timestamp one second -#if defined(PCBSKY9X) +#if defined(COPROCESSOR) if (g_rtcTime < 60 || rtc_count<5) { rtcInit(); rtc_count++; diff --git a/radio/src/targets/sky9x/audio_driver.cpp b/radio/src/targets/sky9x/audio_driver.cpp index d7c5dd323..ed00157b1 100644 --- a/radio/src/targets/sky9x/audio_driver.cpp +++ b/radio/src/targets/sky9x/audio_driver.cpp @@ -136,6 +136,11 @@ void audioInit() pioptr->PIO_PER = 0x02000000L ; // Enable bit A25 (Stock buzzer) pioptr->PIO_OER = 0x02000000L ; // Set bit A25 as output #endif + +#if defined(REVX) + configure_pins( PIO_PC26, PIN_ENABLE | PIN_LOW | PIN_OUTPUT | PIN_PORTC | PIN_NO_PULLUP ) ; + PIOC->PIO_CODR = PIO_PC26 ; +#endif } void audioEnd() @@ -159,19 +164,9 @@ void setVolume(uint8_t volume) { coprocVolumeRequired = volumeScale[min(volume, VOLUME_LEVEL_MAX)]; __disable_irq() ; - coprocCheck() ; + i2cCheck() ; __enable_irq() ; } -#if 0 -void getVolume() -{ - coprocVolumeReadPending = 1 ; - __disable_irq() ; - coprocCheck() ; - __enable_irq() ; -} -#endif - diff --git a/radio/src/targets/sky9x/board_sky9x.cpp b/radio/src/targets/sky9x/board_sky9x.cpp index a2cf97855..5a50c20df 100644 --- a/radio/src/targets/sky9x/board_sky9x.cpp +++ b/radio/src/targets/sky9x/board_sky9x.cpp @@ -606,11 +606,13 @@ void boardInit() adcInit() ; init_pwm() ; - __enable_irq() ; + __enable_irq(); - audioInit() ; + audioInit(); - coprocInit() ; +#if defined(COPROCESSOR) + coprocInit(); +#endif eepromInit(); diff --git a/radio/src/targets/sky9x/board_sky9x.h b/radio/src/targets/sky9x/board_sky9x.h index 873d3e7e5..d2b309f89 100644 --- a/radio/src/targets/sky9x/board_sky9x.h +++ b/radio/src/targets/sky9x/board_sky9x.h @@ -216,13 +216,14 @@ void buzzerSound(uint8_t duration); void buzzerHeartbeat(); #define BUZZER_HEARTBEAT buzzerHeartbeat +// i2c driver +void i2cCheck(); + // Coproc driver void coprocInit(); void coprocWriteData(uint8_t *data, uint32_t size); void coprocReadData(bool onlytemp=false); -void coprocCheck(); extern int8_t coprocVolumeRequired; -extern uint8_t coprocVolumeReadPending; extern uint8_t Coproc_read; extern int8_t Coproc_valid; extern int8_t Coproc_temp; diff --git a/radio/src/targets/sky9x/coproc_driver.cpp b/radio/src/targets/sky9x/coproc_driver.cpp index 8591a52ae..1a9cf190f 100644 --- a/radio/src/targets/sky9x/coproc_driver.cpp +++ b/radio/src/targets/sky9x/coproc_driver.cpp @@ -37,7 +37,6 @@ #include "../../opentx.h" int8_t coprocVolumeRequired ; -uint8_t coprocVolumeReadPending ; uint8_t coprocReadDataPending ; uint8_t coprocWriteDataPending ; uint8_t CoProc_appgo_pending ; @@ -51,7 +50,6 @@ static uint8_t *Twi_read_address ; static uint8_t TwiOperation ; #define TWI_NONE 0 -#define TWI_READ_VOL 1 #define TWI_WRITE_VOL 2 #define TWI_READ_COPROC 3 #define TWI_COPROC_APPGO 4 @@ -72,15 +70,13 @@ uint32_t coprocWriteDataSize ; // This is called from an interrupt routine, or // interrupts must be disabled while it is called // from elsewhere. -void coprocCheck() +void i2cCheck() { - if ( TWI0->TWI_IMR & TWI_IMR_TXCOMP ) - { + if ( TWI0->TWI_IMR & TWI_IMR_TXCOMP ) { return ; // Busy } - if ( coprocVolumeRequired >= 0 ) // Set volume to this value - { + if ( coprocVolumeRequired >= 0 ) { // Set volume to this value TWI0->TWI_MMR = 0x002F0000 ; // Device 5E (>>1) and master is writing TwiOperation = TWI_WRITE_VOL ; TWI0->TWI_THR = coprocVolumeRequired ; // Send data @@ -88,8 +84,7 @@ void coprocCheck() TWI0->TWI_IER = TWI_IER_TXCOMP ; TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx } - else if (coprocReadDataPending) - { + else if (coprocReadDataPending) { Coproc_valid = 0 ; coprocReadDataPending = 0 ; TWI0->TWI_MMR = 0x00351000 ; // Device 35 and master is reading @@ -98,25 +93,14 @@ void coprocCheck() TWI0->TWI_RPR = (uint32_t)&Co_proc_status[0] ; #endif TWI0->TWI_RCR = COPROC_RX_BUXSIZE - 1 ; - if ( TWI0->TWI_SR & TWI_SR_RXRDY ) - { + if ( TWI0->TWI_SR & TWI_SR_RXRDY ) { (void) TWI0->TWI_RHR ; } TWI0->TWI_PTCR = TWI_PTCR_RXTEN ; // Start transfers TWI0->TWI_CR = TWI_CR_START ; // Start Rx TWI0->TWI_IER = TWI_IER_RXBUFF | TWI_IER_TXCOMP ; } - else if (coprocVolumeReadPending) - { - coprocVolumeReadPending = 0 ; - TWI0->TWI_MMR = 0x002F1000 ; // Device 5E (>>1) and master is reading - TwiOperation = TWI_READ_VOL ; - Twi_read_address = &Volume_read ; - TWI0->TWI_CR = TWI_CR_START | TWI_CR_STOP ; // Start and stop Tx - TWI0->TWI_IER = TWI_IER_TXCOMP ; - } - else if ( CoProc_appgo_pending ) - { + else if ( CoProc_appgo_pending ) { CoProc_appgo_pending = 0 ; TWI0->TWI_MMR = 0x00350000 ; // Device 35 and master is writing TwiOperation = TWI_COPROC_APPGO ; @@ -124,8 +108,7 @@ void coprocCheck() TWI0->TWI_IER = TWI_IER_TXCOMP ; TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx } - else if ( coprocWriteDataPending ) - { + else if ( coprocWriteDataPending ) { coprocWriteDataPending = 0 ; TWI0->TWI_MMR = 0x00350000 ; // Device 35 and master is writing TwiOperation = TWI_WRITE_COPROC ; @@ -144,7 +127,7 @@ void coprocReadData(bool onlytemp) get_onlytemp = onlytemp; coprocReadDataPending = 1 ; __disable_irq() ; - coprocCheck() ; + i2cCheck() ; __enable_irq() ; } @@ -154,20 +137,10 @@ void coprocWriteData(uint8_t *data, uint32_t size) coprocWriteDataSize = size; coprocWriteDataPending = 1; __disable_irq(); - coprocCheck(); + i2cCheck(); __enable_irq(); } -#if 0 -void appgo_coprocessor() -{ - CoProc_appgo_pending = 1 ; - __disable_irq() ; - coprocCheck() ; - __enable_irq() ; -} -#endif - // Set up for volume control (TWI0) // Need PA3 and PA4 set to peripheral A void coprocInit() @@ -197,14 +170,6 @@ void coprocInit() #if !defined(SIMU) extern "C" void TWI0_IRQHandler() { - if ( TwiOperation == TWI_READ_VOL ) - { - if ( TWI0->TWI_SR & TWI_SR_RXRDY ) - { - *Twi_read_address = TWI0->TWI_RHR ; // Read data - } - } - if ( TwiOperation == TWI_READ_COPROC ) { if ( TWI0->TWI_SR & TWI_SR_RXBUFF ) @@ -275,6 +240,6 @@ extern "C" void TWI0_IRQHandler() { } TwiOperation = TWI_NONE ; - coprocCheck() ; + i2cCheck() ; } #endif diff --git a/radio/src/targets/sky9x/lcd_driver.cpp b/radio/src/targets/sky9x/lcd_driver.cpp index 9fa3a85e3..4bbedc638 100644 --- a/radio/src/targets/sky9x/lcd_driver.cpp +++ b/radio/src/targets/sky9x/lcd_driver.cpp @@ -88,7 +88,6 @@ const uint8_t Lcd_lookup[] = void lcdSendCtl(uint8_t val) { register Pio *pioptr ; -// register uint32_t x ; #if defined(REVA) pioptr = PIOC ; @@ -98,9 +97,13 @@ void lcdSendCtl(uint8_t val) pioptr->PIO_ODSR = Lcd_lookup[val] ; #else pioptr = PIOC ; - pioptr->PIO_CODR = LCD_CS1 ; // Select LCD + #if !defined(REVX) + pioptr->PIO_CODR = LCD_CS1 ; // Select LCD + #endif PIOA->PIO_CODR = LCD_A0 ; - pioptr->PIO_CODR = LCD_RnW ; // Write + #if !defined(REVX) + pioptr->PIO_CODR = LCD_RnW ; // Write + #endif pioptr->PIO_ODSR = val ; #endif @@ -117,7 +120,10 @@ void lcdSendCtl(uint8_t val) #else PIOA->PIO_SODR = LCD_A0 ; // Data #endif + +#if !defined(REVX) pioptr->PIO_SODR = LCD_CS1 ; // Deselect LCD +#endif } void lcdInit() @@ -126,6 +132,10 @@ void lcdInit() // /home/thus/txt/datasheets/lcd/KS0713.pdf // ~/txt/flieger/ST7565RV17.pdf from http://www.glyn.de/content.asp?wdid=132&sid= + // read the inputs, and lock the LCD lines + lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP () + lcdLock = 1 ; + #if defined(REVA) pioptr = PIOC ; pioptr->PIO_PER = 0x0C00B0FFL ; // Enable bits 27,26,15,13,12,7-0 @@ -136,10 +146,16 @@ void lcdInit() #else configure_pins( LCD_A0, PIN_ENABLE | PIN_LOW | PIN_OUTPUT | PIN_PORTA | PIN_NO_PULLUP ) ; pioptr = PIOC ; - pioptr->PIO_PER = 0x0C0030FFL ; // Enable bits 27,26,13,12,7-0 - pioptr->PIO_CODR = LCD_E | LCD_RnW ; - pioptr->PIO_SODR = LCD_RES | LCD_CS1 ; - pioptr->PIO_OER = 0x0C0030FFL ; // Set bits 27,26,13,12,7-0 output + #if defined(REVX) + pioptr->PIO_PER = PIO_PC27 | PIO_PC12 | 0xFF ; + pioptr->PIO_CODR = LCD_E ; + pioptr->PIO_CODR = LCD_RnW | LCD_CS1 ; // No longer needed, used elsewhere + #else + pioptr->PIO_PER = PIO_PC27 | PIO_PC26 | PIO_PC13 | PIO_PC12 | 0xFF ; + pioptr->PIO_CODR = LCD_E | LCD_RnW | LCD_CS1 ; + #endif + pioptr->PIO_SODR = LCD_RES ; + pioptr->PIO_OER = PIO_PC27 | PIO_PC26 | PIO_PC13 | PIO_PC12 | 0xFF ; // Set bits 27,26,13,12,7-0 output pioptr->PIO_OWER = 0x000000FFL ; // Allow write to ls 8 bits in ODSR #endif @@ -178,6 +194,8 @@ void lcdInit() pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups pioptr->PIO_ODSR = 0 ; // Drive D0 low #endif + + lcdLock = 0 ; } void lcdSetRefVolt(uint8_t val) @@ -246,9 +264,13 @@ void lcdRefresh() lcdSendCtl(0x10); //column addr 0 lcdSendCtl(y | 0xB0); //page addr y - pioptr->PIO_CODR = LCD_CS1; // Select LCD + #if !defined(REVX) + pioptr->PIO_CODR = LCD_CS1; // Select LCD + #endif PIOA->PIO_SODR = LCD_A0; // Data - pioptr->PIO_CODR = LCD_RnW; // Write + #if !defined(REVX) + pioptr->PIO_CODR = LCD_RnW; // Write + #endif #if defined(REVA) x = lookup[*p]; @@ -282,7 +304,9 @@ void lcdRefresh() // } pioptr->PIO_CODR = ebit; // End E pulse } - pioptr->PIO_SODR = LCD_CS1; // Deselect LCD + #if !defined(REVX) + pioptr->PIO_SODR = LCD_CS1; // Deselect LCD + #endif } pioptr->PIO_ODSR = 0xFF ; // Drive lines high diff --git a/radio/src/targets/sky9x/rtc_driver.cpp b/radio/src/targets/sky9x/rtc_driver.cpp index 4e72f2a93..ecda77339 100644 --- a/radio/src/targets/sky9x/rtc_driver.cpp +++ b/radio/src/targets/sky9x/rtc_driver.cpp @@ -36,6 +36,203 @@ #include "../opentx.h" +#if defined(REVX) +// TODO change this, not the right place +#define TWI_NONE 0 +#define TWI_WRITE_VOL 2 +#define TWI_READ_COPROC 3 +#define TWI_WAIT_STOP 5 +#define TWI_WRITE_COPROC 6 +int8_t coprocVolumeRequired ; +static uint8_t TwiOperation ; +#define RTC_RX_BUXSIZE 10 +#define RTC_SIZE 7 +uint8_t Rtc_status[RTC_RX_BUXSIZE] ; +uint8_t *Rtc_write_ptr ; +uint32_t Rtc_write_count ; +uint8_t RtcConfig[8] ; // For initial config and writing to RTC +// 0x80, 0, 0, 0x08, 0, 0, 0, 0x80 + +// This is called from an interrupt routine, or +// interrupts must be disabled while it is called +// from elsewhere. +void i2cCheck() +{ + if ( TWI0->TWI_IMR & TWI_IMR_TXCOMP ) { + return ; // Busy + } + + if ( coprocVolumeRequired >= 0 ) { // Set volume to this value + TWI0->TWI_MMR = 0x002F0000 ; // Device 5E (>>1) and master is writing + TwiOperation = TWI_WRITE_VOL ; + TWI0->TWI_THR = coprocVolumeRequired ; // Send data + Volume_required = -1 ; + TWI0->TWI_IER = TWI_IER_TXCOMP ; + TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx + } + else if ( coprocReadDataPending ) { + Rtc_valid = 0 ; + coprocReadDataPending = 0 ; + TWI0->TWI_MMR = 0x006F1100 ; // Device 6F and master is reading, 1 byte addr + TWI0->TWI_IADR = 0 ; + TwiOperation = TWI_READ_RTC ; +#ifndef SIMU + TWI0->TWI_RPR = (uint32_t)&Rtc_status[0] ; +#endif + TWI0->TWI_RCR = RTC_SIZE - 1 ; + if ( TWI0->TWI_SR & TWI_SR_RXRDY ) + { + (void) TWI0->TWI_RHR ; + } + + if ( ( TWI0->TWI_SR & TWI_SR_TXCOMP ) == 0 ) + { + Debug_I2C_event += 1 ; + } + + TWI0->TWI_PTCR = TWI_PTCR_RXTEN ; // Start transfers + TWI0->TWI_CR = TWI_CR_START ; // Start Rx + TWI0->TWI_IER = TWI_IER_RXBUFF | TWI_IER_TXCOMP ; + } + else if ( coprocWriteDataPending ) { + if ( coprocWriteDataPending & (2|4) ) { + TWI0->TWI_MMR = 0x006F0100 ; // Device 6F and master is writing, 1 byte addr + TwiOperation = TWI_WRITE_MFP ; + if ( Rtc_write_pending & 2 ) { + TWI0->TWI_IADR = 7 ; + TWI0->TWI_THR = MFPsetting ; // Send data + Rtc_write_pending &= ~2 ; + } + else { + TWI0->TWI_IADR = 8 ; + TWI0->TWI_THR = CALsetting ; // Send data + coprocWriteDataPending &= ~4 ; + } + TWI0->TWI_IER = TWI_IER_TXCOMP ; + TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx + } + else { + coprocWriteDataPending &= ~1 ; + TWI0->TWI_MMR = 0x006F0100 ; // Device 6F and master is writing, 1 byte addr + TWI0->TWI_IADR = 0 ; + TwiOperation = TWI_WRITE_RTC ; +#ifndef SIMU + TWI0->TWI_TPR = (uint32_t)Rtc_write_ptr+1 ; +#endif + TWI0->TWI_TCR = Rtc_write_count-1 ; + TWI0->TWI_THR = *Rtc_write_ptr ; // First byte + TWI0->TWI_PTCR = TWI_PTCR_TXTEN ; // Start data transfer + TWI0->TWI_IER = TWI_IER_TXBUFE | TWI_IER_TXCOMP ; + } + } +} + +void writeRTC(uint8_t *ptr) +{ + uint32_t year ; + RtcConfig[0] = 0x80 | toBCD( *ptr++ ) ; + RtcConfig[1] = toBCD( *ptr++ ) ; + RtcConfig[2] = toBCD( *ptr++ ) ; + RtcConfig[3] = 0x08 ; + RtcConfig[4] = toBCD( *ptr++ ) ; + RtcConfig[5] = toBCD( *ptr++ ) ; + year = *ptr++ ; + year |= *ptr << 8 ; + RtcConfig[6] = toBCD( year - 2000 ) ; + RtcConfig[7] = MFPsetting ; + Rtc_write_ptr = RtcConfig ; + Rtc_write_count = 8 ; + __disable_irq() ; + Rtc_write_pending |= 1 ; + i2cCheck() ; + __enable_irq() ; +} + +void readRTC() +{ + Rtc_read_pending = 1 ; + __disable_irq() ; + i2cCheck() ; + __enable_irq() ; +} + +// TODO should be inside an i2c_driver.cpp +#ifndef SIMU +extern "C" void TWI0_IRQHandler() +{ + uint32_t status ; + status = TWI0->TWI_SR ; // Read only once, some bits cleared on read + + if ( TwiOperation == TWI_READ_RTC ) + { + if ( status & TWI_SR_RXBUFF ) + { + TWI0->TWI_IDR = TWI_IDR_RXBUFF ; + TwiOperation = TWI_WAIT_RTCSTOP ; + TWI0->TWI_CR = TWI_CR_STOP ; // Stop Rx + TWI0->TWI_RCR = 1 ; // Last byte + return ; + } + else + { + // must be TXCOMP, prob. NAK in data + if ( TWI0->TWI_RCR > 0 ) + { + Rtc_valid = -1 ; + TWI0->TWI_CR = TWI_CR_STOP ; // Stop Rx + } + } + } + + if ( TwiOperation == TWI_WAIT_RTCSTOP ) + { + Rtc_valid = 1 ; + // Set the date and time + t_time *p = &Time ; + + p->second = fromBCD( Rtc_status[0] & 0x7F ) ; + p->minute = fromBCD( Rtc_status[1] & 0x7F ) ; + p->hour = fromBCD( Rtc_status[2] & 0x3F ) ; + p->date = fromBCD( Rtc_status[4] & 0x3F ) ; + p->month = fromBCD( Rtc_status[5] & 0x1F ) ; + p->year = fromBCD( Rtc_status[6] ) + 2000 ; + + TWI0->TWI_PTCR = TWI_PTCR_RXTDIS ; // Stop transfers + if ( status & TWI_SR_RXRDY ) + { + (void) TWI0->TWI_RHR ; // Discard any rubbish data + } + } + + if ( status & TWI_SR_NACK ) + { + Debug_I2C_event += 0x100 ; + TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx + } + + if ( status & TWI_SR_RXBUFF ) + { + if ( TWI0->TWI_IMR & TWI_IMR_RXBUFF ) + { + Debug_I2C_event += 0x1000000 ; + } + } + + TWI0->TWI_IDR = TWI_IDR_TXCOMP | TWI_IDR_TXBUFE | TWI_IDR_RXBUFF ; + TWI0->TWI_PTCR = TWI_PTCR_TXTDIS | TWI_PTCR_RXTDIS ; // Stop transfers + if ( ( status & TWI_SR_TXCOMP ) == 0 ) + { + TWI0->TWI_IER = TWI_IER_TXCOMP ; + TwiOperation = TWI_WAIT_COMP ; + return ; + } + + TwiOperation = TWI_NONE ; + i2cCheck() ; +} +#endif +#endif + struct t_i2cTime { uint8_t setCode ; @@ -55,7 +252,11 @@ void rtcSetTime(struct gtm * t) I2CTime.Time[4] = t->tm_mon+1 ; I2CTime.Time[5] = (uint8_t) (t->tm_year+1900); I2CTime.Time[6] = (t->tm_year+1900) >> 8; +#if defined(REVX) + writeRTC( (uint8_t *) &I2CTime.Time[0], 8 ) ; +#else coprocWriteData((uint8_t *) &I2CTime, 8); +#endif } void rtcInit()