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/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 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 a540350..3838daa 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 @@ -198,7 +202,108 @@ .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! +.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) +.endif + +; enable adc reading if USE_ADC or USE_ADC_MASK is defined +.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) +.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 +; 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 >= 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 +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 brake_active: .byte 1 ; Type of brake active + +.if USE_ADC_MASK +adc_temp_l: .byte 1 ; the accumulating adc low +adc_temp_h: .byte 1 ; the accumulating adc high +adc_temp_x: .byte 1 ; the accumulating adc extended +adc_temp_mux: .byte 1 ; the mux to read now +adc_temp_count: .byte 1 ; number of samples accumulated so far (counting down) + +.macro adc_mux_define + .if USE_ADC_MASK & (1<<@0) + ; define the real values in sram +adc_mux_l: .byte 1 ; value low +adc_mux_h: .byte 1 ; value high + ; define aliases for this address if one of the following muxes is set + .equ adc_mux_@0 = adc_mux_l + .equ adc_mux_@0_l = adc_mux_l + .equ adc_mux_@0_h = adc_mux_h + .if defined(mux_a) + .if (@0 == mux_a) + .equ adc_mux_a_l = adc_mux_l + .equ adc_mux_a_h = adc_mux_h + .if defined(mux_a_mul) + .equ adc_mux_@0_mul = mux_a_mul + .endif + .if defined(mux_a_off) + .equ adc_mux_@0_off = mux_a_off + .endif + .endif + .endif + .if defined(mux_b) + .if (@0 == mux_b) + .equ adc_mux_b_l = adc_mux_l + .equ adc_mux_b_h = adc_mux_h + .if defined(mux_b_mul) + .equ adc_mux_@0_mul = mux_b_mul + .endif + .if defined(mux_b_off) + .equ adc_mux_@0_off = mux_b_off + .endif + .endif + .endif + .if defined(mux_c) + .if (@0 == mux_c) + .equ adc_mux_c_l = adc_mux_l + .equ adc_mux_c_h = adc_mux_h + .if defined(mux_c_mul) + .equ adc_mux_@0_mul = mux_c_mul + .endif + .if defined(mux_c_off) + .equ adc_mux_@0_off = mux_c_off + .endif + .endif + .endif + .if defined(mux_common) + .if (@0 == mux_common) + .equ adc_mux_common_l = adc_mux_l + .equ adc_mux_common_h = adc_mux_h + .if defined(mux_common_mul) + .equ adc_mux_@0_mul = mux_common_mul + .endif + .if defined(mux_common_off) + .equ adc_mux_@0_off = mux_common_off + .endif + .endif + .endif + .if defined(mux_voltage) + .if (@0 == mux_voltage) + .equ adc_mux_voltage_l = adc_mux_l + .equ adc_mux_voltage_h = adc_mux_h + .if defined(mux_voltage_mul) + .equ adc_mux_@0_mul = mux_voltage_mul + .endif + .if defined(mux_voltage_off) + .equ adc_mux_@0_off = mux_voltage_off + .endif + .endif + .endif + .if defined(mux_current) + .if (@0 == mux_current) + .equ adc_mux_current_l = adc_mux_l + .equ adc_mux_current_h = adc_mux_h + .if defined(mux_current_mul) + .equ adc_mux_@0_mul = mux_current_mul + .endif + .if defined(mux_current_off) + .equ adc_mux_@0_off = mux_current_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 + .endif + .if (@0 == 15) + .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 +adc_mux_define 0 +adc_mux_define 1 +adc_mux_define 2 +adc_mux_define 3 +adc_mux_define 4 +adc_mux_define 5 +adc_mux_define 6 +adc_mux_define 7 +.if USE_ADC_MASK & ((1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<12) | (1<<13)) +.error "Unsupported ADC MUX mask - some MUX between 8 and 13 enabled" +.endif +adc_mux_define 14 +adc_mux_define 15 +.endif ;**** **** **** **** **** ; The following entries are block-copied from/to EEPROM eeprom_sig_l: .byte 1 @@ -418,6 +646,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 @@ -614,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) @@ -1199,6 +1453,18 @@ eeprom_defaults_w: ;-- RC pulse setup and edge handling macros ------------------------------ +.macro int0_set_rising_edge + in @0, MCUCR + sbr @0, (1< 1) || USE_ADC_MASK +.macro adc_disable + out ADCSRA, Zh +.endmacro + +.macro adc_enable_slow_irq + 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 + .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 + + ; 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 + sbrc temp1, TOIE1 +.if USE_ADC_MASK + rjmp adc_process_skip_t1ovf_sim +.else + ret +.endif + ; disable/enable the ADC temporarily, so that we run longer conversion + ; resulting in less interrupts/s (IRQ/s reduction ratio: 13/25) + ; resulting in longer sleeps, which saves power + cbi ADCSRA, ADEN + sbi ADCSRA, ADEN + ; decrement t1 overflow simulator 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 + ; call the t1ovfl_int (this will reenable irq) + rcall t1ovfl_int + ; reset the timer counter to top (assuming extended conversions) + ldi temp1, ADC_SLEEP_COUNTER_TOP +adc_process_no_ovfl_sim: + ; store the counter + 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 + 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 + + ; 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 + ; 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 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 + 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 + 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 temp4, (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 +.macro adc_check_mux +.if USE_ADC_MASK & (1<<@0) + ; define the first ADC if not set + .if !defined(USE_ADC_FIRST) + .equ USE_ADC_FIRST = @0 + .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 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 + 2 + .else + ; 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 + ; 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) +adc_check_mux_skip: +.endif +.endmacro + +; 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 + + ; 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 + + ; 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 + ; 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< 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 + + ; Wait for one of the input sources to give arming input i_rc_puls1: clr rc_timeout cbr flags1, (1< 1 || USE_ADC_MASK + rcall adc_process + .endif + .if USE_SLEEP + rcall sleep_adc + .endif .if defined(HK_PROGRAM_CARD) .endif sbrc flags1, EVAL_RC @@ -3444,20 +4223,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 - rjmp i_rc_puls2 + .if USE_SLEEP > 1 + rcall sleep_set_adc ; fall back to adc sleep mode + .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 - brne i_rc_puls1 + 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 brlo i_rc_puls2 @@ -3485,6 +4269,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<