From 6a0482a74d7bf28d6336c999f78e182f9b5d088c Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Sat, 31 Oct 2015 18:08:07 +0000 Subject: [PATCH 01/11] implemented idle sleep Measurements tgy@10.9V: * sleep = 0 * 48.3mA no PWM/PWM (no PWM generator) * 56.4mA PWM neutral armed (including PWM-generator) * 1761 Words * sleep = 1 * 38.8mA no PWM (no PWM generator) * 46.7mA PWM neutral armed (including PWM-generator) * 1776 Words * reduction of 9.5-9.7mA * change * -9.5mA no PWM (no PWM generator) * -9.7mA PWM neutral armed (including PWM-generator) * +16 Words Measurements afro_nfet@10.9V: * sleep = 0 * 44.9mA no PWM/PWM (no PWM generator) * 60.6mA PWM neutral armed (including PWM-generator) * 2086 Words * sleep = 1 * 37.8mA no PWM (no PWM generator) * 54.3mA PWM neutral armed (including PWM-generator) * 2101 Words * change * -7.1mA no PWM (no PWM generator) * -6.3mA PWM neutral armed (including PWM-generator) * +16 Words --- tgy.asm | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/tgy.asm b/tgy.asm index a540350..8ddf070 100644 --- a/tgy.asm +++ b/tgy.asm @@ -188,8 +188,12 @@ .equ RC_PULS_REVERSE = 0 ; Enable RC-car style forward/reverse throttle .equ RC_CALIBRATION = 1 ; Support run-time calibration of min/max pulse lengths .equ SLOW_THROTTLE = 0 ; Limit maximum throttle jump to try to prevent overcurrent +.if !defined(BEACON) .equ BEACON = 1 ; Beep periodically when RC signal is lost +.endif +.if !defined(BEACON_IDLE) .equ BEACON_IDLE = 0 ; Beep periodically if idle for a long period +.endif .if !defined(CHECK_HARDWARE) .equ CHECK_HARDWARE = 0 ; Check for correct pin configuration, sense inputs, and functioning MOSFETs .endif @@ -200,6 +204,16 @@ .equ DEBUG_ADC_DUMP = 0 ; Output an endless loop of all ADC values (no normal operation) .equ MOTOR_DEBUG = 0 ; Output sync pulses on MOSI or SCK, debug flag on MISO +; power saving when the motor is not running +.if !defined(USE_SLEEP) +.equ USE_SLEEP = 0 ; Sleep level to support (0 = none, 1 = idle) +.endif +.if USE_SLEEP +.equ SLEEP_FLAGS = (1< Date: Mon, 2 Nov 2015 14:42:49 +0000 Subject: [PATCH 02/11] use common macros to set INT0 edge reduces code we need to maintain --- tgy.asm | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tgy.asm b/tgy.asm index 8ddf070..e62aaf9 100644 --- a/tgy.asm +++ b/tgy.asm @@ -1213,6 +1213,18 @@ eeprom_defaults_w: ;-- RC pulse setup and edge handling macros ------------------------------ +.macro int0_set_rising_edge + in @0, MCUCR + sbr @0, (1< Date: Tue, 3 Nov 2015 15:18:02 +0000 Subject: [PATCH 03/11] suport deeper sleep mode using ADC Allow the use of USE_SLEEP=2 to mean we run with ADC-sleep when idle As the timer does not work in adc-sleep, we use the extended ADC conversion to simulate the 4096us overflow interrupt of T1. Measurements tgy@10.9V: * SLEEP = 0 * 48.9mA idle - no PWM * 47.3mA armed - with neutral PWM * 1773 Words * SLEEP = 1 * 38.8mA idle - no PWM * 38.8mA armed - with neutral PWM * 1789 Words * SLEEP = 2 * 33.7mA idle - no PWM - requires PWM pulldown!!! * 38.8mA armed - with neutral PWM * 1839 Words Measurements afro_nfet@10.9V: * SLEEP = 0 * 45.2mA idle - no PWM * 53.5mA armed - with neutral PWM * 2094 Words * SLEEP = 1 * 38.4mA idle - no PWM * 46.9mA armed - with neutral PWM * 2110 Words * SLEEP = 2 * 35.6mA idle - no PWM - requires PWM pulldown!!! * 46.9mA armed - with neutral PWM * 2170 Words --- tgy.asm | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 179 insertions(+), 12 deletions(-) diff --git a/tgy.asm b/tgy.asm index e62aaf9..ca2f9b4 100644 --- a/tgy.asm +++ b/tgy.asm @@ -206,12 +206,34 @@ ; power saving when the motor is not running .if !defined(USE_SLEEP) -.equ USE_SLEEP = 0 ; Sleep level to support (0 = none, 1 = idle) +.equ USE_SLEEP = 0 ; Sleep level to support (0 = none, 1 = idle, 2=adc) .endif -.if USE_SLEEP -.equ SLEEP_FLAGS = (1< 1) + .if defined(HK_PROGRAM_CARD) || USE_UART +.warning "There are some restrictions when using deeper sleep and UART" +; note: the implementation for wakeup from sleep requires that +; the UART-RX line goes low for at least 0.2ms +; this comes "out of the box" as the UART-protocol needs to send: +; 0xf5 0x00 (n times - depending on motor count) +; more than 10 times for the system to move into "armed" mode +; and sending 0x00 at 38400Baud takes the line down for 0.23ms +; set sampling to 1ms effectively for long conversions +; this is a bit more expensive power wise due to twice/four times +; the number of interrupts compared to full idle + .if F_CPU >= 16 +.equ ADC_IDLE_CLOCK_DIV = 64 +.equ ADC_IDLE_CLOCK_BIT = (1< 1 +adc_timer_counter: .byte 1 ; counter +.endif motor_count: .byte 1 ; Motor number for serial control brake_sub: .byte 1 ; Brake speed subtrahend (power of two) brake_want: .byte 1 ; Type of brake desired @@ -1215,13 +1240,13 @@ eeprom_defaults_w: .macro int0_set_rising_edge in @0, MCUCR - sbr @0, (1< 1 +.macro adc_disable + out ADCSRA, Zh +.endmacro + +.macro adc_enable_slow_irq + outi ADCSRA, (1< 1 + + ; disable rcp_int + rcp_int_disable temp1 + + ; enable sleep mode ADC + sleep_enable temp1, 1 + + ; enable ADC with irq and slow clock + adc_enable_slow_irq temp1 + + ; disable timer1 overflow interrupt + in temp1, TIMSK + cbr temp1, (1< 1 + ; disable ADC + adc_disable temp1 + ; enable timer1 overflow + in temp1, TIMSK + sbr temp1, (1< 1 + ; only consider to sleep in deep sleep if adc is running + sbis ADCSRA, ADSC ret +.endif sleep_idle: ; atomically check if we should sleep cli sbrc flags1, EVAL_RC reti + ; read state of RXD pin before and after sleep + .if USE_SLEEP > 1 + .if defined(HK_PROGRAM_CARD) || USE_UART + in temp2, PIND + andi temp2, (1< 1 + ; if adc_int is disabled then return + sbis ADCSRA, ADIE + ret + ; if there is a pulse level on the RC pins then return to idle sleep + .if USE_INT0 = 1 + sbic PIND, rcp_in + rjmp sleep_set_idle + .elseif USE_INT0 = 2 + sbis PIND, rcp_in + rjmp sleep_set_idle + .elseif USE_ICP + sbic PINB, rcp_in + rjmp sleep_set_idle + .endif + .if defined(HK_PROGRAM_CARD) || USE_UART + ; need to check if there was a uart pin-change since before the sleep + in temp1, PIND + andi temp1, (1< 1 + rcall sleep_set_adc + rjmp i_rc_puls1 +.endif + +i_rc_puls1_sleep_idle: .if USE_SLEEP rcall sleep_set_idle .endif @@ -3493,8 +3649,11 @@ i_rc_puls1: clr rc_timeout sts rct_boot, ZH sts rct_beacon, ZH i_rc_puls2: wdr + .if USE_SLEEP > 1 + rcall adc_process + .endif .if USE_SLEEP - rcall sleep_idle + rcall sleep_adc .endif .if defined(HK_PROGRAM_CARD) .endif @@ -3503,20 +3662,25 @@ i_rc_puls2: wdr .if BOOT_JUMP rcall boot_loader_test .endif - .if BEACON + .if BEACON || (USE_SLEEP > 1) lds temp1, rct_beacon cpi temp1, 120 ; Beep every 120 * 16 * 65536us (~8s) brne i_rc_puls2 ldi temp1, 60 sts rct_beacon, temp1 ; Double rate after the first beep + .endif + .if BEACON rcall beep_f3 ; Beacon .endif + .if USE_SLEEP > 1 + rcall sleep_set_adc ; fall back to adc sleep mode + .endif rjmp i_rc_puls2 i_rc_puls_rx: rcall evaluate_rc_init lds YL, rc_duty_l lds YH, rc_duty_h adiw YL, 0 ; Test for zero - brne i_rc_puls1 + brne i_rc_puls1_sleep_idle ldi temp1, 10 ; wait for this count of receiving power off cp rc_timeout, temp1 brlo i_rc_puls2 @@ -3544,6 +3708,9 @@ i_rc_puls3: ; Fall through to restart_control ;-----bko----------------------------------------------------------------- restart_control: +.if USE_SLEEP + rcall sleep_set_idle +.endif rcall switch_power_off ; Disables PWM timer, turns off all FETs cbr flags0, (1< Date: Tue, 3 Nov 2015 16:40:36 +0000 Subject: [PATCH 04/11] added USE_LED_PWM to reduce power consumption of green led when armed When armed and in neutral my afro-esc consumes (with USE_SLEEP=2): * USE_LED_PWM = 0 - 47.4mA * USE_LED_PWM = 1 - 43.1mA * USE_LED_PWM = 2 - 40.9mA (flashes already) * USE_LED_PWM = 3 - 39.9mA * USE_LED_PWM = 4 - 39.3mA * USE_LED_PWM = 5 - 39.1mA * USE_LED_PWM = 6 - 38.1mA so there is some power that can get saved by implementing that --- tgy.asm | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tgy.asm b/tgy.asm index ca2f9b4..2ef5f65 100644 --- a/tgy.asm +++ b/tgy.asm @@ -204,6 +204,10 @@ .equ DEBUG_ADC_DUMP = 0 ; Output an endless loop of all ADC values (no normal operation) .equ MOTOR_DEBUG = 0 ; Output sync pulses on MOSI or SCK, debug flag on MISO +.if !defined(USE_LED_PWM) +.equ USE_LED_PWM = 0 ; set to 1/2/3 to set PWM fequency and brightness - 3 flashes already! +.endif + ; power saving when the motor is not running .if !defined(USE_SLEEP) .equ USE_SLEEP = 0 ; Sleep level to support (0 = none, 1 = idle, 2=adc) @@ -3757,6 +3761,17 @@ set_brake_duty: ldi2 temp1, temp2, MAX_POWER wait_for_power_on: wdr + ; GREEN-led PWM based on T1 overflow to save some power + .if USE_LED_PWM && defined(green_led) + lds temp3, tcnt1x + andi temp3, (1< Date: Tue, 3 Nov 2015 17:33:37 +0000 Subject: [PATCH 05/11] implement low power FET mode while idle/armed but neutral This sets up the FET in such a mode that we save on power consumption Example config for afro_nfet: .equ USE_SLEEP = 2 .equ USE_LED_PWM = 3 ;***************************************** ; ENABLE_LOW_POWER_FET_MODE during sleep * ;***************************************** .equ USE_FET_SET_LOW_POWER = 1 .MACRO FET_SET_LOW_POWER cbi AnFET_port,AnFET cbi BnFET_port,BnFET cbi CnFET_port,CnFET cbi ApFET_port,ApFET cbi BpFET_port,BpFET cbi CpFET_port,CpFET .ENDMACRO .equ USE_FET_RESET_LOW_POWER = 1 .MACRO FET_RESET_LOW_POWER cbi AnFET_port,AnFET cbi BnFET_port,BnFET cbi CnFET_port,CnFET sbi ApFET_port,ApFET sbi BpFET_port,BpFET sbi CpFET_port,CpFET .ENDMACRO This results in: * stock (1e4c01782eff85da3971f628a3bd599b7a0725eb): * 45.2mA idle - no PWM * 53.5mA armed - with neutral PWM * 2094 Words * USE_SLEEP=2 and USE_LED_PWM=3: * 35.6mA idle - no PWM * 39.8mA armed - with neutral PWM * 2177 Words * USE_FET_* = 1 + all sleep and led optimizations * 19.9mA idle - no PWM * 23.5mA armed - with neutral PWM * 2198 Words --- tgy.asm | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/tgy.asm b/tgy.asm index 2ef5f65..d466f8c 100644 --- a/tgy.asm +++ b/tgy.asm @@ -1815,12 +1815,49 @@ urxc_set_exit: sts motor_count, i_temp2 urxc_exit: out SREG, i_sreg reti .endif +;-----bko----------------------------------------------------------------- +; macros to embed low power FET settings into code mit minimal overhead +.macro FET_LOW_POWER_RESTORE + .if defined(USE_FET_RESET_LOW_POWER) + .if USE_FET_RESET_LOW_POWER + rcall _fet_low_power_reset + .endif + .endif +.endmacro +.macro FET_LOW_POWER_SET + .if defined(USE_FET_SET_LOW_POWER) + .if USE_FET_SET_LOW_POWER + rcall _fet_low_power_set + .endif + .endif +.endmacro + +.if defined(USE_FET_RESET_LOW_POWER) +.if USE_FET_RESET_LOW_POWER +_fet_low_power_reset: + ; put system in a low power mode from a FET perspective + FET_RESET_LOW_POWER + + ret +.endif +.endif +.if defined(USE_FET_SET_LOW_POWER) +.if USE_FET_SET_LOW_POWER +_fet_low_power_set: + ; put system in a normal power mode from a FET perspective + FET_SET_LOW_POWER + + ret +.endif +.endif + ;-----bko----------------------------------------------------------------- ; beeper: timer0 is set to 1µs/count beep_f1: ldi temp2, 80 ldi temp4, 200 RED_on BLUE_on + FET_LOW_POWER_RESTORE beep_f1_on: BpFET_on AnFET_on rcall beep @@ -1833,6 +1870,7 @@ beep_f2: ldi temp2, 100 ldi temp4, 180 GRN_on BLUE_on + FET_LOW_POWER_RESTORE beep_f2_on: CpFET_on BnFET_on rcall beep @@ -1844,6 +1882,7 @@ beep_f2_on: CpFET_on beep_f3: ldi temp2, 120 ldi temp4, 160 BLUE_on + FET_LOW_POWER_RESTORE beep_f3_on: ApFET_on CnFET_on rcall beep @@ -1856,6 +1895,7 @@ beep_f4_freq: ldi temp4, 140 beep_f4_fets: RED_on GRN_on BLUE_on + FET_LOW_POWER_RESTORE beep_f4_on: CpFET_on AnFET_on rcall beep @@ -3652,6 +3692,8 @@ i_rc_puls1: clr rc_timeout cbr flags1, (1< 1 rcall adc_process @@ -3679,7 +3721,7 @@ i_rc_puls2: wdr .if USE_SLEEP > 1 rcall sleep_set_adc ; fall back to adc sleep mode .endif - rjmp i_rc_puls2 + rjmp i_rc_puls2_low_power i_rc_puls_rx: rcall evaluate_rc_init lds YL, rc_duty_l lds YH, rc_duty_h @@ -3731,7 +3773,7 @@ wait_for_power_on_init: lds temp3, brake_want lds temp4, brake_active cp temp3, temp4 - breq wait_for_power_on + breq wait_for_power_on_low_power rcall switch_power_off ; Disable any active brake sts brake_active, temp3 ; Set new brake_active to brake_want @@ -3744,7 +3786,7 @@ wait_for_power_on_init: rjmp set_brake_duty set_brake1: cpi temp3, 2 ; Thumb brake - brne wait_for_power_on + brne wait_for_power_on_low_power ldi YL, 1 << low(LOW_BRAKE_SPEED) sts brake_sub, YL ldi2 YL, YH, LOW_BRAKE_POWER @@ -3758,7 +3800,8 @@ set_brake_duty: ldi2 temp1, temp2, MAX_POWER clr sys_control_l ; Abused as duty update divisor outi TCCR2, T2CLK, temp1 ; Enable PWM, cleared later by switch_power_off .endif - +wait_for_power_on_low_power: + FET_LOW_POWER_SET wait_for_power_on: wdr ; GREEN-led PWM based on T1 overflow to save some power @@ -3820,6 +3863,7 @@ wait_for_power_rx: breq wait_for_power_on_init ; while resetting boot/beacon timers start_from_running: + FET_LOW_POWER_RESTORE ; put system in a normal power mode rcall switch_power_off comp_init temp1 ; init comparator RED_off From 5cde1525958b26cb4c8acdf47ca2700134550fac Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Wed, 4 Nov 2015 20:03:56 +0000 Subject: [PATCH 06/11] sample ADC channels on a regular basis and oversample the result This implements 256 x ADC oversampling with 2 bit decimation to result in a result value range of [0:65472] There is also some scaling offset calculation that can get applied to the gathered values. when USE_ADC = 1 is set then we look for defined: * mux_temperature * mux_voltage * mux_current and calculate the mask of adc channels to use. Alternatively USE_ADC_MASK can be set to a bitmask of the ADC channels to capture - note that there are no Channels 8 - 13, so if any of these bits are set the build will fail . For example with afro_nfet on can define: .equ USE_ADC = 1 .equ mux_voltage_mul = (5*256*(18000+3300)/3300) to get the voltage scaled correctly to: Vbat*256 Note that typically an oversample of a channel takes: 0.1037s for a motor running at aprox 1400 commutation cycles/s 0.0282s for an unarmed ESC note that when armed the sample rate may go as low as 1 second - especially when braking or accelerating. Also there is no sampling happening while the ESC is "beeping"! Last thing missing is exporting those numbers via I2C... --- tgy.asm | 344 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 336 insertions(+), 8 deletions(-) diff --git a/tgy.asm b/tgy.asm index d466f8c..4218687 100644 --- a/tgy.asm +++ b/tgy.asm @@ -202,7 +202,9 @@ .equ CELL_COUNT = 0 ; 0: auto, >0: hard-coded number of cells (for reliable LVC > ~4S) .equ BLIP_CELL_COUNT = 0 ; Blip out cell count before arming .equ DEBUG_ADC_DUMP = 0 ; Output an endless loop of all ADC values (no normal operation) +.if !defined(MOTOR_DEBUG) .equ MOTOR_DEBUG = 0 ; Output sync pulses on MOSI or SCK, debug flag on MISO +.endif .if !defined(USE_LED_PWM) .equ USE_LED_PWM = 0 ; set to 1/2/3 to set PWM fequency and brightness - 3 flashes already! @@ -213,7 +215,38 @@ .equ USE_SLEEP = 0 ; Sleep level to support (0 = none, 1 = idle, 2=adc) .endif -.if (USE_SLEEP > 1) +; enable adc reading if USE_ADC or USE_ADC_MASK is defined +.if !defined(USE_ADC) +.equ USE_ADC = defined(USE_ADC_MASK) +.endif + +; calculate the USE_ADC_MASK from some well-known MUX +.if !defined(USE_ADC_MASK) +.set USE_ADC_MASK = 0 ; the ADC bitmap is set to 0 by default +.if USE_ADC +.if defined(mux_voltage) +.set USE_ADC_MASK = USE_ADC_MASK | (1< 1) || USE_ADC_MASK .if defined(HK_PROGRAM_CARD) || USE_UART .warning "There are some restrictions when using deeper sleep and UART" ; note: the implementation for wakeup from sleep requires that @@ -225,12 +258,20 @@ ; set sampling to 1ms effectively for long conversions ; this is a bit more expensive power wise due to twice/four times ; the number of interrupts compared to full idle - .if F_CPU >= 16 + .if F_CPU >= 12 +; when idle use 250kHz ADC clock @16MHz (187kHz@12MHz - 312kHz@20MHz) .equ ADC_IDLE_CLOCK_DIV = 64 .equ ADC_IDLE_CLOCK_BIT = (1< 1 +.if (USE_SLEEP > 1) || USE_ADC_MASK .macro adc_disable out ADCSRA, Zh .endmacro .macro adc_enable_slow_irq - outi ADCSRA, (1< 1 + .if USE_SLEEP > 1 || USE_ADC_MASK rcall adc_process .endif .if USE_SLEEP @@ -3723,9 +4040,9 @@ i_rc_puls2: wdr .endif rjmp i_rc_puls2_low_power i_rc_puls_rx: rcall evaluate_rc_init - lds YL, rc_duty_l - lds YH, rc_duty_h - adiw YL, 0 ; Test for zero + lds Yl, rc_duty_l + lds Yl, rc_duty_h + adiw Yl, 0 ; Test for zero brne i_rc_puls1_sleep_idle ldi temp1, 10 ; wait for this count of receiving power off cp rc_timeout, temp1 @@ -3814,6 +4131,9 @@ wait_for_power_on: wait_for_power_blink_green_skip_on: GRN_off wait_for_power_blink_green_skip_off: + .endif + .if USE_ADC_MASK + rcall adc_process .endif .if USE_SLEEP rcall sleep_idle @@ -3865,6 +4185,9 @@ wait_for_power_rx: start_from_running: FET_LOW_POWER_RESTORE ; put system in a normal power mode rcall switch_power_off + .if USE_ADC_MASK + adc_enable_fast temp1 ; set up adc with fast clock + .endif comp_init temp1 ; init comparator RED_off GRN_off @@ -4330,6 +4653,11 @@ wait_for_edge2: sbrs flags0, OCT1_PENDING wait_for_edge3: dec XL ; Zero-cross has happened brne wait_for_edge2 ; Check again unless temp1 is zero + ; trigger ADC read while we wait for commutations... + .if USE_ADC_MASK + rcall adc_process + .endif + wait_commutation: flag_on rcall update_timing From dad05d419727feea44de4546ad220f3e4c3092cf Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Tue, 10 Nov 2015 15:11:01 +0000 Subject: [PATCH 07/11] added ADC_DEBUG option output on PORTB5 if available --- tgy.asm | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/tgy.asm b/tgy.asm index 4218687..d41fce8 100644 --- a/tgy.asm +++ b/tgy.asm @@ -219,6 +219,14 @@ .if !defined(USE_ADC) .equ USE_ADC = defined(USE_ADC_MASK) .endif +; adc debugging settings tpically on PORTB5 +.if !defined(ADC_DEBUG) +.equ ADC_DEBUG = 0 ; if =1 : typical mask bit 1-3 set + ; bit 1 : high when ADC Running + ; bit 2 : high when aggregating + ; bit 3 : high when in final processing + ; bit 4 : toggle DEBUG when in adc_processing +.endif ; calculate the USE_ADC_MASK from some well-known MUX .if !defined(USE_ADC_MASK) @@ -3493,13 +3501,62 @@ rcp_error_beep_more: .macro adc_enable_fast outi ADCSRA, (1<0.1ms when idle) +; 1 short high means we have a real value that we aggregate (~1.6us) +; 2 short high (short, then a bit longer) means we are finalizing a value (~3.5us) +; so it looks like this: +; _^^^^^^^^^^^^^^_^^^^^^^^^^^^^^_ - conversion, but aborted - changed mux +; _^^^^^^^^^^^^^^_^_^^^^^^^^^^^^^^_ - conversion and aggregation of values +; _^^^^^^^^^^^^^^_^_^^_^^^^^^^^^^^^^^_ - conversion and aggregation and +; storing of final value (scaled) + +.macro adc_on + ; only if B5 is available and MOTOR_DEBUG does not claim B5 + .if ADC_DEBUG && (DIR_PB & (1<<5)) == 0 + .if !MOTOR_DEBUG || (DIR_PB & (1<<3)) == 0 + .if (ADC_DEBUG == 1) || ADC_DEBUG & (1<<@0) + sbi PORTB, 5 + .endif + .endif +.endmacro + +.macro adc_off + ; only if B5 is available and MOTOR_DEBUG does not claim B5 + .if ADC_DEBUG && (DIR_PB & (1<<5)) == 0 + .if !MOTOR_DEBUG || (DIR_PB & (1<<3)) == 0 + cbi PORTB, 5 + .endif + .endif +.endmacro + +.macro adc_toggle + ; only if B5 is available and MOTOR_DEBUG does not claim B5 + .if (ADC_DEBUG & (1<<4)) && (DIR_PB & (1<<5)) == 0 + .if !MOTOR_DEBUG || (DIR_PB & (1<<3)) == 0 + in temp1, PORTB + ldi temp2, (1<<5) + eor temp1, temp2 + out PORTB, temp1 + eor temp1, temp2 + out PORTB, temp1 + .endif + .endif +.endmacro adc_process: + + ; adc debug marker - in adc_process + adc_toggle 4 + ; if adc is running there is nothing to do sbic ADCSRA, ADSC ret - ; if T1OVF ADCIE is enabled, skipthe T1 4.096ms simulation via adc + ; adc debug marker - end of conversion + adc_off + +.if USE_SLEEP > 1 + ; if T1OVF ADCIE is enabled, skip the T1 4.096ms simulation via adc in temp1, TIMSK sbrc temp1, TOIE1 .if USE_ADC_MASK @@ -3525,6 +3582,7 @@ adc_process_no_ovfl_sim: ; store the counter sts adc_timer_counter, temp1 adc_process_skip_t1ovf_sim: +.endif .if USE_ADC_MASK adc_process_values: @@ -3534,6 +3592,9 @@ adc_process_values: andi temp1, 15 cp temp1, temp2 brne adc_start_set_mux + ; adc debug marker - start of aggregation + adc_on 2 + ; read 10bit ADCL/H and add to 24-bit adc_temp_l/h/x ; with 256 samples this allows an effecive range of 18 bit ; note that ADC values are left aligned, so bits 15-6 are used @@ -3558,6 +3619,9 @@ adc_process_values: sts adc_temp_h, temp5 sts adc_temp_x, temp6 adc_start_set_mux: + ; adc debug marker - end of aggregation final result + adc_off + ; set up MUX with the correct ADC_REF set as well as left aligned ori temp2, (1< Date: Tue, 10 Nov 2015 15:18:19 +0000 Subject: [PATCH 08/11] afro_nfet enable lowest power mode and adc reading by default This already includes definitions for ADC value transformation --- afro_nfet.inc | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/afro_nfet.inc b/afro_nfet.inc index 0ae28e0..5c116d1 100644 --- a/afro_nfet.inc +++ b/afro_nfet.inc @@ -9,6 +9,9 @@ .equ USE_I2C = 1 .equ USE_UART = 1 .equ USE_ICP = 1 +.equ USE_SLEEP = 2 +.equ USE_LED_PWM = 3 +.equ USE_ADC = 1 .equ DEAD_LOW_NS = 300 .equ DEAD_HIGH_NS = 300 @@ -37,7 +40,12 @@ ; PORT C definitions * ;********************* .equ mux_voltage = 7 ; ADC7 voltage input (18k from Vbat, 3.3k to gnd, 10.10V -> 1.565V at ADC7) +.equ mux_voltage_mul = (5*256*(18000+3300)/3300) +.equ mux_voltage_off = 0 .equ mux_temperature = 6 ; ADC6 temperature input (3.3k from +5V, 10k NTC to gnd) +.equ mux_temperature_rpullup = 3300 +.equ mux_temperature_rntc = 10000 +.equ mux_temperature_beta = 3950 .equ i2c_clk = 5 ; ADC5/SCL .equ i2c_data = 4 ; ADC4/SDA .equ red_led = 3 ; o @@ -62,7 +70,7 @@ .ENDMACRO .MACRO GRN_off cbi DDRC, green_led -.ENDMACRO +.ENDMACRO ;********************* ; PORT D definitions * @@ -83,3 +91,27 @@ .equ BnFET_port = PORTD .equ CnFET_port = PORTD .equ ApFET_port = PORTD + +;***************************************** +; ENABLE_LOW_POWER_FET_MODE during sleep * +;***************************************** +.equ USE_FET_SET_LOW_POWER = 1 +.equ USE_FET_RESET_LOW_POWER = 1 + +.MACRO FET_SET_LOW_POWER +cbi AnFET_port,AnFET +cbi BnFET_port,BnFET +cbi CnFET_port,CnFET +cbi ApFET_port,ApFET +cbi BpFET_port,BpFET +cbi CpFET_port,CpFET +.ENDMACRO + +.MACRO FET_RESET_LOW_POWER +cbi AnFET_port,AnFET +cbi BnFET_port,BnFET +cbi CnFET_port,CnFET +sbi ApFET_port,ApFET +sbi BpFET_port,BpFET +sbi CpFET_port,CpFET +.ENDMACRO From bdc7ff5b50c7dd5ccea4cc11f8789ff6393a16a5 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Tue, 10 Nov 2015 15:44:07 +0000 Subject: [PATCH 09/11] added ntc translation table when mux_temperature* are defined This will load a generated translation of ADC to a temperature value from flash into SRAM for later use by the ADC translation layer --- Makefile | 7 +- create-ntc-table.sh | 56 ++++++++++ ntc-table.inc | 266 ++++++++++++++++++++++++++++++++++++++++++++ tgy.asm | 83 +++++++++++--- 4 files changed, 397 insertions(+), 15 deletions(-) create mode 100755 create-ntc-table.sh create mode 100644 ntc-table.inc diff --git a/Makefile b/Makefile index 05a1429..66d3fe1 100644 --- a/Makefile +++ b/Makefile @@ -10,8 +10,8 @@ AUX_TARGETS = afro_pr0.hex afro_pr1.hex diy0.hex all: $(ALL_TARGETS) -$(ALL_TARGETS): tgy.asm boot.inc -$(AUX_TARGETS): tgy.asm boot.inc +$(ALL_TARGETS): tgy.asm boot.inc ntc-table.inc +$(AUX_TARGETS): tgy.asm boot.inc ntc-table.inc .inc.hex: @test -e $*.asm || ln -s tgy.asm $*.asm @@ -24,6 +24,9 @@ test: all clean: -rm -f $(ALL_TARGETS) *.cof *.obj *.eep.hex *.eeprom +ntc-table.inc: create-ntc-table.sh *.inc + ./create-ntc-table.sh > $@ + binary_zip: $(ALL_TARGETS) TARGET="tgy_`date '+%Y-%m-%d'`_`git rev-parse --verify --short HEAD`"; \ mkdir "$$TARGET" && \ diff --git a/create-ntc-table.sh b/create-ntc-table.sh new file mode 100755 index 0000000..b2e3d9c --- /dev/null +++ b/create-ntc-table.sh @@ -0,0 +1,56 @@ +#! /bin/sh + +RPULLUP_VALUES="`awk -F= '/^\.equ[ \t]*mux_temperature_rpullup/{C[$2]++}END{for(i in C){if(i!=0)printf "%i ",i;}}' *.inc`" +RNTC_VALUES="`awk -F= '/^\.equ[ \t]*mux_temperature_rntc[ \t]*=/{C[$2]++}END{for(i in C){if(i!=0)printf "%i ",i;}}' *.inc`" +BETA_VALUES="`awk -F= '/^\.equ[ \t]*mux_temperature_beta[ \t]*=/{C[$2]++}END{for(i in C){if(i!=0)printf "%i ",i;}}' *.inc`" + +test -z "$1" || RPULLUP_VALUES=$1 +test -z "$2" || RNTC_VALUES=$2 +test -z "$3" || BETA_VALUES=$3 + +echo "; NTC thermal tables" +echo "; generated via script: $0" +echo ".if defined(mux_temperature_rpullup) && defined(mux_temperature_rntc) && defined(mux_temperature_beta)" +( +for R in $RPULLUP_VALUES; do + for T in $RNTC_VALUES; do + for B in $BETA_VALUES; do + echo "$R $T $B"; + done + done +done +) | awk ' +function printline(A,B) { + # scale and saturate + C=B*256; + if (C<-32768){ C=-32768; } + if (C>32767){ C=32767; } + TS=C/256; + if (C<0){C+=65536}; + # and print + printf "\t.dw 0x%04x\t; ADC = %4i, Temp = %6.1fC\n", C, A, TS; +} +{ + RPULLUP=$1; + RTHERMAL=$2; + BETA=$3; + printf ";----------------------------------------------------------------\n"; + printf "; RPULLUP = %i, RTHERMAL = %i, BETA = %i\n", RPULLUP, RTHERMAL, BETA; + printf ".%sif (mux_temperature_rpullup == %i) && (mux_temperature_rntc == %i) && (mux_temperature_beta == %i)\n", PREFIX, RPULLUP, RTHERMAL, BETA; + PREFIX="else"; + printline(0, -100*RPULLUP); + for(ADC=1;ADC<255;ADC++){ + # handle both pullups/pulldowns + if (RPULLUP<0) { + X=-((255/(255-ADC))-1)*RPULLUP/RTHERMAL; + } else { + X=((255/ADC)-1)*RPULLUP/RTHERMAL; + } + # do the real calculation + ITK=log(X)/BETA + 1/(273.15+25); + T=1/ITK -273.15; + printline(ADC,T) + } + printline(255, 100*RPULLUP); +} +END{if (NR>0) {printf ".else\n\t.error \"No corresponding BETA, RPULLUP and RNTC values found - please recreate ntc-table.inc via make to reflect your changes to .inc\"\n.endif\n.endif\n";}}' diff --git a/ntc-table.inc b/ntc-table.inc new file mode 100644 index 0000000..ae3d9ce --- /dev/null +++ b/ntc-table.inc @@ -0,0 +1,266 @@ +; NTC thermal tables +; generated via script: ./create-ntc-table.sh +.if defined(mux_temperature_rpullup) && defined(mux_temperature_rntc) && defined(mux_temperature_beta) +;---------------------------------------------------------------- +; RPULLUP = 3300, RTHERMAL = 10000, BETA = 3950 +.if (mux_temperature_rpullup == 3300) && (mux_temperature_rntc == 10000) && (mux_temperature_beta == 3950) + .dw 0x8000 ; ADC = 0, Temp = -128.0C + .dw 0xce4d ; ADC = 1, Temp = -49.7C + .dw 0xd77a ; ADC = 2, Temp = -40.5C + .dw 0xdd39 ; ADC = 3, Temp = -34.8C + .dw 0xe17e ; ADC = 4, Temp = -30.5C + .dw 0xe4ed ; ADC = 5, Temp = -27.1C + .dw 0xe7d1 ; ADC = 6, Temp = -24.2C + .dw 0xea53 ; ADC = 7, Temp = -21.7C + .dw 0xec8c ; ADC = 8, Temp = -19.5C + .dw 0xee8c ; ADC = 9, Temp = -17.5C + .dw 0xf05f ; ADC = 10, Temp = -15.6C + .dw 0xf20d ; ADC = 11, Temp = -13.9C + .dw 0xf39c ; ADC = 12, Temp = -12.4C + .dw 0xf511 ; ADC = 13, Temp = -10.9C + .dw 0xf670 ; ADC = 14, Temp = -9.6C + .dw 0xf7bb ; ADC = 15, Temp = -8.3C + .dw 0xf8f5 ; ADC = 16, Temp = -7.0C + .dw 0xfa20 ; ADC = 17, Temp = -5.9C + .dw 0xfb3d ; ADC = 18, Temp = -4.8C + .dw 0xfc4e ; ADC = 19, Temp = -3.7C + .dw 0xfd55 ; ADC = 20, Temp = -2.7C + .dw 0xfe51 ; ADC = 21, Temp = -1.7C + .dw 0xff44 ; ADC = 22, Temp = -0.7C + .dw 0x0030 ; ADC = 23, Temp = 0.2C + .dw 0x0113 ; ADC = 24, Temp = 1.1C + .dw 0x01f0 ; ADC = 25, Temp = 1.9C + .dw 0x02c7 ; ADC = 26, Temp = 2.8C + .dw 0x0397 ; ADC = 27, Temp = 3.6C + .dw 0x0462 ; ADC = 28, Temp = 4.4C + .dw 0x0528 ; ADC = 29, Temp = 5.2C + .dw 0x05e9 ; ADC = 30, Temp = 5.9C + .dw 0x06a5 ; ADC = 31, Temp = 6.6C + .dw 0x075d ; ADC = 32, Temp = 7.4C + .dw 0x0812 ; ADC = 33, Temp = 8.1C + .dw 0x08c2 ; ADC = 34, Temp = 8.8C + .dw 0x096f ; ADC = 35, Temp = 9.4C + .dw 0x0a19 ; ADC = 36, Temp = 10.1C + .dw 0x0ac0 ; ADC = 37, Temp = 10.8C + .dw 0x0b64 ; ADC = 38, Temp = 11.4C + .dw 0x0c04 ; ADC = 39, Temp = 12.0C + .dw 0x0ca3 ; ADC = 40, Temp = 12.6C + .dw 0x0d3e ; ADC = 41, Temp = 13.2C + .dw 0x0dd8 ; ADC = 42, Temp = 13.8C + .dw 0x0e6f ; ADC = 43, Temp = 14.4C + .dw 0x0f04 ; ADC = 44, Temp = 15.0C + .dw 0x0f96 ; ADC = 45, Temp = 15.6C + .dw 0x1027 ; ADC = 46, Temp = 16.2C + .dw 0x10b6 ; ADC = 47, Temp = 16.7C + .dw 0x1143 ; ADC = 48, Temp = 17.3C + .dw 0x11cf ; ADC = 49, Temp = 17.8C + .dw 0x1259 ; ADC = 50, Temp = 18.3C + .dw 0x12e1 ; ADC = 51, Temp = 18.9C + .dw 0x1368 ; ADC = 52, Temp = 19.4C + .dw 0x13ed ; ADC = 53, Temp = 19.9C + .dw 0x1471 ; ADC = 54, Temp = 20.4C + .dw 0x14f3 ; ADC = 55, Temp = 21.0C + .dw 0x1575 ; ADC = 56, Temp = 21.5C + .dw 0x15f5 ; ADC = 57, Temp = 22.0C + .dw 0x1674 ; ADC = 58, Temp = 22.5C + .dw 0x16f2 ; ADC = 59, Temp = 22.9C + .dw 0x176e ; ADC = 60, Temp = 23.4C + .dw 0x17ea ; ADC = 61, Temp = 23.9C + .dw 0x1865 ; ADC = 62, Temp = 24.4C + .dw 0x18df ; ADC = 63, Temp = 24.9C + .dw 0x1958 ; ADC = 64, Temp = 25.3C + .dw 0x19d0 ; ADC = 65, Temp = 25.8C + .dw 0x1a47 ; ADC = 66, Temp = 26.3C + .dw 0x1abd ; ADC = 67, Temp = 26.7C + .dw 0x1b33 ; ADC = 68, Temp = 27.2C + .dw 0x1ba8 ; ADC = 69, Temp = 27.7C + .dw 0x1c1c ; ADC = 70, Temp = 28.1C + .dw 0x1c8f ; ADC = 71, Temp = 28.6C + .dw 0x1d02 ; ADC = 72, Temp = 29.0C + .dw 0x1d74 ; ADC = 73, Temp = 29.5C + .dw 0x1de6 ; ADC = 74, Temp = 29.9C + .dw 0x1e57 ; ADC = 75, Temp = 30.3C + .dw 0x1ec8 ; ADC = 76, Temp = 30.8C + .dw 0x1f37 ; ADC = 77, Temp = 31.2C + .dw 0x1fa7 ; ADC = 78, Temp = 31.7C + .dw 0x2016 ; ADC = 79, Temp = 32.1C + .dw 0x2084 ; ADC = 80, Temp = 32.5C + .dw 0x20f3 ; ADC = 81, Temp = 32.9C + .dw 0x2160 ; ADC = 82, Temp = 33.4C + .dw 0x21cd ; ADC = 83, Temp = 33.8C + .dw 0x223a ; ADC = 84, Temp = 34.2C + .dw 0x22a7 ; ADC = 85, Temp = 34.7C + .dw 0x2313 ; ADC = 86, Temp = 35.1C + .dw 0x237f ; ADC = 87, Temp = 35.5C + .dw 0x23eb ; ADC = 88, Temp = 35.9C + .dw 0x2456 ; ADC = 89, Temp = 36.3C + .dw 0x24c1 ; ADC = 90, Temp = 36.8C + .dw 0x252c ; ADC = 91, Temp = 37.2C + .dw 0x2596 ; ADC = 92, Temp = 37.6C + .dw 0x2600 ; ADC = 93, Temp = 38.0C + .dw 0x266a ; ADC = 94, Temp = 38.4C + .dw 0x26d4 ; ADC = 95, Temp = 38.8C + .dw 0x273e ; ADC = 96, Temp = 39.2C + .dw 0x27a8 ; ADC = 97, Temp = 39.7C + .dw 0x2811 ; ADC = 98, Temp = 40.1C + .dw 0x287b ; ADC = 99, Temp = 40.5C + .dw 0x28e4 ; ADC = 100, Temp = 40.9C + .dw 0x294d ; ADC = 101, Temp = 41.3C + .dw 0x29b6 ; ADC = 102, Temp = 41.7C + .dw 0x2a1f ; ADC = 103, Temp = 42.1C + .dw 0x2a88 ; ADC = 104, Temp = 42.5C + .dw 0x2af1 ; ADC = 105, Temp = 42.9C + .dw 0x2b59 ; ADC = 106, Temp = 43.4C + .dw 0x2bc2 ; ADC = 107, Temp = 43.8C + .dw 0x2c2b ; ADC = 108, Temp = 44.2C + .dw 0x2c94 ; ADC = 109, Temp = 44.6C + .dw 0x2cfd ; ADC = 110, Temp = 45.0C + .dw 0x2d66 ; ADC = 111, Temp = 45.4C + .dw 0x2dcf ; ADC = 112, Temp = 45.8C + .dw 0x2e38 ; ADC = 113, Temp = 46.2C + .dw 0x2ea1 ; ADC = 114, Temp = 46.6C + .dw 0x2f0a ; ADC = 115, Temp = 47.0C + .dw 0x2f73 ; ADC = 116, Temp = 47.5C + .dw 0x2fdd ; ADC = 117, Temp = 47.9C + .dw 0x3046 ; ADC = 118, Temp = 48.3C + .dw 0x30b0 ; ADC = 119, Temp = 48.7C + .dw 0x311a ; ADC = 120, Temp = 49.1C + .dw 0x3184 ; ADC = 121, Temp = 49.5C + .dw 0x31ee ; ADC = 122, Temp = 49.9C + .dw 0x3258 ; ADC = 123, Temp = 50.3C + .dw 0x32c3 ; ADC = 124, Temp = 50.8C + .dw 0x332e ; ADC = 125, Temp = 51.2C + .dw 0x3399 ; ADC = 126, Temp = 51.6C + .dw 0x3404 ; ADC = 127, Temp = 52.0C + .dw 0x3470 ; ADC = 128, Temp = 52.4C + .dw 0x34dc ; ADC = 129, Temp = 52.9C + .dw 0x3548 ; ADC = 130, Temp = 53.3C + .dw 0x35b5 ; ADC = 131, Temp = 53.7C + .dw 0x3621 ; ADC = 132, Temp = 54.1C + .dw 0x368f ; ADC = 133, Temp = 54.6C + .dw 0x36fc ; ADC = 134, Temp = 55.0C + .dw 0x376a ; ADC = 135, Temp = 55.4C + .dw 0x37d8 ; ADC = 136, Temp = 55.8C + .dw 0x3847 ; ADC = 137, Temp = 56.3C + .dw 0x38b6 ; ADC = 138, Temp = 56.7C + .dw 0x3926 ; ADC = 139, Temp = 57.2C + .dw 0x3996 ; ADC = 140, Temp = 57.6C + .dw 0x3a07 ; ADC = 141, Temp = 58.0C + .dw 0x3a78 ; ADC = 142, Temp = 58.5C + .dw 0x3ae9 ; ADC = 143, Temp = 58.9C + .dw 0x3b5b ; ADC = 144, Temp = 59.4C + .dw 0x3bce ; ADC = 145, Temp = 59.8C + .dw 0x3c41 ; ADC = 146, Temp = 60.3C + .dw 0x3cb5 ; ADC = 147, Temp = 60.7C + .dw 0x3d29 ; ADC = 148, Temp = 61.2C + .dw 0x3d9e ; ADC = 149, Temp = 61.6C + .dw 0x3e13 ; ADC = 150, Temp = 62.1C + .dw 0x3e8a ; ADC = 151, Temp = 62.5C + .dw 0x3f01 ; ADC = 152, Temp = 63.0C + .dw 0x3f78 ; ADC = 153, Temp = 63.5C + .dw 0x3ff1 ; ADC = 154, Temp = 63.9C + .dw 0x406a ; ADC = 155, Temp = 64.4C + .dw 0x40e4 ; ADC = 156, Temp = 64.9C + .dw 0x415e ; ADC = 157, Temp = 65.4C + .dw 0x41da ; ADC = 158, Temp = 65.9C + .dw 0x4256 ; ADC = 159, Temp = 66.3C + .dw 0x42d3 ; ADC = 160, Temp = 66.8C + .dw 0x4352 ; ADC = 161, Temp = 67.3C + .dw 0x43d1 ; ADC = 162, Temp = 67.8C + .dw 0x4451 ; ADC = 163, Temp = 68.3C + .dw 0x44d2 ; ADC = 164, Temp = 68.8C + .dw 0x4554 ; ADC = 165, Temp = 69.3C + .dw 0x45d7 ; ADC = 166, Temp = 69.8C + .dw 0x465b ; ADC = 167, Temp = 70.4C + .dw 0x46e0 ; ADC = 168, Temp = 70.9C + .dw 0x4766 ; ADC = 169, Temp = 71.4C + .dw 0x47ee ; ADC = 170, Temp = 71.9C + .dw 0x4877 ; ADC = 171, Temp = 72.5C + .dw 0x4901 ; ADC = 172, Temp = 73.0C + .dw 0x498c ; ADC = 173, Temp = 73.6C + .dw 0x4a19 ; ADC = 174, Temp = 74.1C + .dw 0x4aa7 ; ADC = 175, Temp = 74.7C + .dw 0x4b37 ; ADC = 176, Temp = 75.2C + .dw 0x4bc8 ; ADC = 177, Temp = 75.8C + .dw 0x4c5a ; ADC = 178, Temp = 76.4C + .dw 0x4cee ; ADC = 179, Temp = 76.9C + .dw 0x4d84 ; ADC = 180, Temp = 77.5C + .dw 0x4e1b ; ADC = 181, Temp = 78.1C + .dw 0x4eb4 ; ADC = 182, Temp = 78.7C + .dw 0x4f4f ; ADC = 183, Temp = 79.3C + .dw 0x4fec ; ADC = 184, Temp = 79.9C + .dw 0x508b ; ADC = 185, Temp = 80.5C + .dw 0x512b ; ADC = 186, Temp = 81.2C + .dw 0x51ce ; ADC = 187, Temp = 81.8C + .dw 0x5273 ; ADC = 188, Temp = 82.5C + .dw 0x531a ; ADC = 189, Temp = 83.1C + .dw 0x53c3 ; ADC = 190, Temp = 83.8C + .dw 0x546f ; ADC = 191, Temp = 84.4C + .dw 0x551d ; ADC = 192, Temp = 85.1C + .dw 0x55ce ; ADC = 193, Temp = 85.8C + .dw 0x5681 ; ADC = 194, Temp = 86.5C + .dw 0x5737 ; ADC = 195, Temp = 87.2C + .dw 0x57f0 ; ADC = 196, Temp = 87.9C + .dw 0x58ac ; ADC = 197, Temp = 88.7C + .dw 0x596b ; ADC = 198, Temp = 89.4C + .dw 0x5a2d ; ADC = 199, Temp = 90.2C + .dw 0x5af2 ; ADC = 200, Temp = 90.9C + .dw 0x5bbb ; ADC = 201, Temp = 91.7C + .dw 0x5c88 ; ADC = 202, Temp = 92.5C + .dw 0x5d58 ; ADC = 203, Temp = 93.3C + .dw 0x5e2c ; ADC = 204, Temp = 94.2C + .dw 0x5f05 ; ADC = 205, Temp = 95.0C + .dw 0x5fe2 ; ADC = 206, Temp = 95.9C + .dw 0x60c3 ; ADC = 207, Temp = 96.8C + .dw 0x61a9 ; ADC = 208, Temp = 97.7C + .dw 0x6294 ; ADC = 209, Temp = 98.6C + .dw 0x6384 ; ADC = 210, Temp = 99.5C + .dw 0x647a ; ADC = 211, Temp = 100.5C + .dw 0x6575 ; ADC = 212, Temp = 101.5C + .dw 0x6677 ; ADC = 213, Temp = 102.5C + .dw 0x677f ; ADC = 214, Temp = 103.5C + .dw 0x688d ; ADC = 215, Temp = 104.6C + .dw 0x69a3 ; ADC = 216, Temp = 105.6C + .dw 0x6ac0 ; ADC = 217, Temp = 106.8C + .dw 0x6be6 ; ADC = 218, Temp = 107.9C + .dw 0x6d13 ; ADC = 219, Temp = 109.1C + .dw 0x6e4a ; ADC = 220, Temp = 110.3C + .dw 0x6f8b ; ADC = 221, Temp = 111.5C + .dw 0x70d6 ; ADC = 222, Temp = 112.8C + .dw 0x722b ; ADC = 223, Temp = 114.2C + .dw 0x738d ; ADC = 224, Temp = 115.6C + .dw 0x74fb ; ADC = 225, Temp = 117.0C + .dw 0x7676 ; ADC = 226, Temp = 118.5C + .dw 0x7800 ; ADC = 227, Temp = 120.0C + .dw 0x799b ; ADC = 228, Temp = 121.6C + .dw 0x7b46 ; ADC = 229, Temp = 123.3C + .dw 0x7d03 ; ADC = 230, Temp = 125.0C + .dw 0x7ed6 ; ADC = 231, Temp = 126.8C + .dw 0x7fff ; ADC = 232, Temp = 128.0C + .dw 0x7fff ; ADC = 233, Temp = 128.0C + .dw 0x7fff ; ADC = 234, Temp = 128.0C + .dw 0x7fff ; ADC = 235, Temp = 128.0C + .dw 0x7fff ; ADC = 236, Temp = 128.0C + .dw 0x7fff ; ADC = 237, Temp = 128.0C + .dw 0x7fff ; ADC = 238, Temp = 128.0C + .dw 0x7fff ; ADC = 239, Temp = 128.0C + .dw 0x7fff ; ADC = 240, Temp = 128.0C + .dw 0x7fff ; ADC = 241, Temp = 128.0C + .dw 0x7fff ; ADC = 242, Temp = 128.0C + .dw 0x7fff ; ADC = 243, Temp = 128.0C + .dw 0x7fff ; ADC = 244, Temp = 128.0C + .dw 0x7fff ; ADC = 245, Temp = 128.0C + .dw 0x7fff ; ADC = 246, Temp = 128.0C + .dw 0x7fff ; ADC = 247, Temp = 128.0C + .dw 0x7fff ; ADC = 248, Temp = 128.0C + .dw 0x7fff ; ADC = 249, Temp = 128.0C + .dw 0x7fff ; ADC = 250, Temp = 128.0C + .dw 0x7fff ; ADC = 251, Temp = 128.0C + .dw 0x7fff ; ADC = 252, Temp = 128.0C + .dw 0x7fff ; ADC = 253, Temp = 128.0C + .dw 0x7fff ; ADC = 254, Temp = 128.0C + .dw 0x7fff ; ADC = 255, Temp = 128.0C +.else + .error "No corresponding BETA, RPULLUP and RNTC values found - please recreate ntc-table.inc via make to reflect your changes to .inc" +.endif +.endif diff --git a/tgy.asm b/tgy.asm index d41fce8..c722c65 100644 --- a/tgy.asm +++ b/tgy.asm @@ -254,6 +254,23 @@ .equ USE_ADC_REF = (1< 1) || USE_ADC_MASK .if defined(HK_PROGRAM_CARD) || USE_UART .warning "There are some restrictions when using deeper sleep and UART" @@ -578,19 +595,6 @@ adc_mux_h: .byte 1 ; value high .endif .endif .endif - .if defined(mux_temperature) - .if (@0 == mux_temperature) - .equ adc_mux_temperature_l = adc_mux_l - .equ adc_mux_temperature_h = adc_mux_h - .if defined(mux_temperature_mul) - .equ adc_mux_@0_mul = mux_temperature_mul - .endif - .if defined(mux_voltage_off) - .equ adc_mux_@0_off = mux_temperature_off - .endif - - .endif - .endif .if (@0 == 14) .equ adc_mux_voltage_bg_l = adc_mux_l .equ adc_mux_voltage_bg_h = adc_mux_h @@ -637,6 +641,14 @@ blc_bitconfig: .byte 1 ; BLConfig bitconfig (1 == MOTOR_REVERSE) blc_checksum: .byte 1 ; BLConfig checksum (0xaa + above bytes) .endif eeprom_end: .byte 1 +;**** **** **** **** **** +; The following entries are block-copied from FLASH +copy_to_sram_start: +.if USE_ADC_TEMPERATURE_NTC_TABLE +adc_ntc_table: .byte 512 ; the NTC translation table +.endif +copy_to_sram_end: + ;-----bko----------------------------------------------------------------- ;**** **** **** **** **** .cseg @@ -3518,6 +3530,7 @@ rcp_error_beep_more: sbi PORTB, 5 .endif .endif + .endif .endmacro .macro adc_off @@ -3855,6 +3868,45 @@ sleep_idle: .endif ret .endif + +;-----bko----------------------------------------------------- +; table spaces copied to sram starting at copy_to_sram_start +.macro check_flash_sram_offset + .if 2*(@0_flash-copy_from_flash_start) != (@0-copy_to_sram_start) + .error "There are different offsets defined in flash compared to sram" + .endif +.endmacro + +copy_from_flash_start: +.if USE_ADC_TEMPERATURE_NTC_TABLE +adc_ntc_table_flash: + check_flash_sram_offset adc_ntc_table +.include "ntc-table.inc" +.endif +copy_from_flash_end: + +; check that sizes match +.if (2*(copy_from_flash_end-copy_from_flash_start)) != (copy_to_sram_end-copy_to_sram_start) +.error "mismatch between flash and sram table space sizes" +.endif + +; copy data from flash into sram +.if copy_from_flash_start != copy_from_flash_end +copy_from_flash_to_sram: + ldi2 Xl, Xh, copy_to_sram_start + ldi2 Zl, Zh, 2 * copy_from_flash_start + +copy_from_flash_loop: + lpm temp1, Z+ + st X+, temp1 + cpiz2 Xl, Xh, copy_to_sram_end, temp2 + brne copy_from_flash_loop + + clr Zh + + ret +.endif + ;-----bko----------------------------------------------------------------- main: clr r0 @@ -3930,6 +3982,11 @@ clear_loop1: cp ZL, r0 rcall eeprom_read_block ; Also calls osccal_set rcall eeprom_check_reset + ; copy flash to sram if we got something to copy + .if copy_from_flash_start != copy_from_flash_end + rcall copy_from_flash_to_sram + .endif + ; Early input initialization is required for i2c BL-Ctrl V2 detection ; This serves data from the EEPROM, so this is as early as possible. .if USE_I2C From 3eed22082a7107db2493f07d9a5b6bbed50a92ae Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Tue, 10 Nov 2015 15:46:54 +0000 Subject: [PATCH 10/11] fixed spacing issues --- tgy.asm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tgy.asm b/tgy.asm index c722c65..7a66755 100644 --- a/tgy.asm +++ b/tgy.asm @@ -270,7 +270,6 @@ .equ USE_ADC_TEMPERATURE_NTC_TABLE = 0 .endif - .if (USE_SLEEP > 1) || USE_ADC_MASK .if defined(HK_PROGRAM_CARD) || USE_UART .warning "There are some restrictions when using deeper sleep and UART" @@ -645,7 +644,7 @@ eeprom_end: .byte 1 ; The following entries are block-copied from FLASH copy_to_sram_start: .if USE_ADC_TEMPERATURE_NTC_TABLE -adc_ntc_table: .byte 512 ; the NTC translation table +adc_ntc_table: .byte 512 ; the NTC translation table .endif copy_to_sram_end: From 725cda70314f322f7b4fd8371922810335fc8092 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Wed, 11 Nov 2015 08:14:55 +0000 Subject: [PATCH 11/11] added NTC transformation and inlined the scaling/offset code --- tgy.asm | 225 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 147 insertions(+), 78 deletions(-) diff --git a/tgy.asm b/tgy.asm index 7a66755..3838daa 100644 --- a/tgy.asm +++ b/tgy.asm @@ -602,6 +602,12 @@ adc_mux_h: .byte 1 ; value high .equ adc_mux_voltage_gnd_l = adc_mux_l .equ adc_mux_voltage_gnd_h = adc_mux_h .endif + .if !defined(adc_mux_@0_mul) + .equ adc_mux_@0_mul = 1 + .endif + .if !defined(adc_mux_@0_off) + .equ adc_mux_@0_off = 0 + .endif .endif .endmacro adc_mux_start: ; the mux low and high as well as the next mux @@ -844,6 +850,24 @@ eeprom_defaults_w: .endif .endmacro +; load via Y offset if possible +.macro lddy + .if ((@1-@2) < 64) && (@1>=@2) + ldd @0, Y+(@1-@2) + .else + lds @0, @1 + .endif +.endmacro + +; store via Y offset if possible +.macro stdy + .if ((@0-@2) < 64) && (@0 >= @2) + std Y+(@0-@2), @1 + .else + sts @0, @1 + .endif +.endmacro + ;-- LED macros ----------------------------------------------------------- .if !defined(red_led) @@ -3567,6 +3591,9 @@ adc_process: ; adc debug marker - end of conversion adc_off + ; load Y with adc_temp_l + ldi2 Yl, Yh, adc_temp_l + .if USE_SLEEP > 1 ; if T1OVF ADCIE is enabled, skip the T1 4.096ms simulation via adc in temp1, TIMSK @@ -3582,7 +3609,7 @@ adc_process: cbi ADCSRA, ADEN sbi ADCSRA, ADEN ; decrement t1 overflow simulator counter - lds temp1, adc_timer_counter + lddy temp1, adc_timer_counter, adc_temp_l dec temp1 ; if we reach 0 then we have a simulated overflow so about 4ms brne adc_process_no_ovfl_sim @@ -3592,17 +3619,17 @@ adc_process: ldi temp1, ADC_SLEEP_COUNTER_TOP adc_process_no_ovfl_sim: ; store the counter - sts adc_timer_counter, temp1 + stdy adc_timer_counter, temp1, adc_temp_l adc_process_skip_t1ovf_sim: .endif .if USE_ADC_MASK adc_process_values: ; only run if the set mux match the requested - lds temp2, adc_temp_mux - in temp1, ADMUX - andi temp1, 15 - cp temp1, temp2 + lddy temp4, adc_temp_mux, adc_temp_l + in temp3, ADMUX + andi temp3, 15 + cp temp4, temp3 brne adc_start_set_mux ; adc debug marker - start of aggregation adc_on 2 @@ -3612,31 +3639,31 @@ adc_process_values: ; note that ADC values are left aligned, so bits 15-6 are used ; so we decimate by 2 LSB by just using temp_h/x and dropping ; temp_l resulting in a 16-bit ADC value in the range [0:65472] - ; note that the order of accumulated values [l,h,x] is temp7, 5, 6 - lds temp7, adc_temp_l - in temp1, ADCL - add temp7, temp1 - lds temp5, adc_temp_h - in temp1, ADCH - adc temp5, temp1 - lds temp6, adc_temp_x - adc temp6, ZH + ; note that the order of accumulated values [l,h,x] is temp5, 1, 2 + lddy temp5, adc_temp_l, adc_temp_l + lddy temp1, adc_temp_h, adc_temp_l + lddy temp2, adc_temp_x, adc_temp_l + in temp6, ADCL + add temp5, temp6 + in temp6, ADCH + adc temp1, temp6 + adc temp2, ZH ; check if we overflow adc_temp_count - lds temp1, adc_temp_count - dec temp1 - sts adc_temp_count, temp1 + lddy temp6, adc_temp_count, adc_temp_l + dec temp6 + stdy adc_temp_count, temp6, adc_temp_l breq adc_process_store_aggregated ; store the temp value - sts adc_temp_l, temp7 - sts adc_temp_h, temp5 - sts adc_temp_x, temp6 + stdy adc_temp_l, temp5, adc_temp_l + stdy adc_temp_h, temp1, adc_temp_l + stdy adc_temp_x, temp2, adc_temp_l adc_start_set_mux: ; adc debug marker - end of aggregation final result adc_off ; set up MUX with the correct ADC_REF set as well as left aligned - ori temp2, (1< 0 + .if adc_mux_@0_off + adiwx temp1, temp2, adc_mux_@0_off + .endif + .endif +.endmacro ; helper macro to store the current averaged value and select next mux +; temp5/1/2 contain the 24 bit value ; temp3 contains current mux ; temp4 contains next mux (on exit) ; XL/Xh contain adc_base @@ -3660,59 +3729,74 @@ adc_start_set_mux: .endif ; to finish up the last iteration of adc_check_mux ; load the next mux (= this iteration) + ; this is also the default when mux does not match ldi temp4, @0 + ; and jump immediately to value store (if not the first in sequence) + .if USE_ADC_FIRST != @0 + rjmp adc_process_value_mux_store + .endif ; compare current with mux cpi temp3, @0 - ; if we are not equal then jump to the end plus 1, - ; so that we get past the load for temp2 + ; if we are not equal then jump to the end plus 2, + ; so that we get past the load for temp2 and the exit jump .if USE_ADC_MASK & (65534 << @0) - brne adc_check_mux_skip + 1 + brne adc_check_mux_skip + 2 .else - brne adc_check_mux_skip + ; or if we are the last, then just update the MUX to first... + ; - by default temp4 contains USE_ADC_FIRST... + brne adc_process_mux_store .endif - ; load the destination register in X by adding the offset - ; so we are limited to 32 muxes, which is ok - ; with 10/16 mux available in HW + ; do the adc_translation + adc_translate_value @0 + + ; load the destination address in X by adding the offset + ; so we are limited to < 31 muxes, which is ok + ; with 10/16 mux available on the Mega8/XX8 adiw Xl, (adc_mux_@0_l - adc_temp_l) - ; add scaling and offsets if set - .if defined(adc_mux_@0_mul) - .if adc_mux_@0_mul - ldi2 temp1, temp2, adc_mux_@0_mul - .endif - .endif - .if defined(adc_mux_@0_off) - .if adc_mux_@0_off - ldi2 Yl, Yh, adc_mux_@0_off - .endif - .endif adc_check_mux_skip: .endif .endmacro -; scale the 24 bit value -; store aggregated 24 bit value to final location -; get next mux to use -adc_process_store_aggregated: +; scale the aggregted 18 bit value (temp5,1,2) +; temp5 contains value bit0,1 in bit 6 and 7, which we will decimate +; store aggregated 16 bit value to final sram location for the mux +; calculate next mux to use +adc_process_store_aggregated: ; adc debug marker - end of aggregation adc_off - ; load current mux in temp1 for comparisson - temp2 will contain next - lds temp3, adc_temp_mux - ; load X with adc_temp_l - ldi2 Xl, Xh, adc_temp_l + ; clear temp using Y (which here still contains adc_temp_l) + stdy adc_temp_l, Zh, adc_temp_l + stdy adc_temp_h, Zh, adc_temp_l + stdy adc_temp_x, Zh, adc_temp_l - ; set up default multiplier and offsets - ldi2 temp1, temp2, 0 ; multiplier - movw Yl, temp1 + ; load X with adc_temp_l (is in Y) + movw Xl, Yl + + ; clear Y + .if byte1(adc_temp_l) + clr Yl + .endif + .if byte2(adc_temp_l) + clr Yh + .endif ; adc debug marker - start of final result adc_on 3 ; now the real mux-checks - ; this will take 1+COUNT_BITS(USE_ADC_MASK)*3+1/2 cycles - ; so in the worsted case (0-7 and 14, 15) 32/33 cycles - ; but there are typically 3 MUX that we could be - ; interrested, which leaves us at 10 cycles, which is not so bad + ; as of now there is no longer a constant execution length + ; as we have added scaling translation into the mix directly + ; if no scaling/translation happens we run: + ; + 3C * BITCOUNT(USE_ADC_MASK & ((1<