/* * Copyright (c) 2010, Joshua Lackey * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "arfcn_freq.h" const char *bi_to_str(int bi) { switch(bi) { case GSM_850: return "GSM-850"; case GSM_R_900: return "GSM-R-900"; case GSM_900: return "GSM-900"; case GSM_E_900: return "E-GSM-900"; case DCS_1800: return "DCS-1800"; case PCS_1900: return "PCS-1900"; default: return "unknown band indicator"; } } int str_to_bi(char *s) { if(!strcmp(s, "GSM850") || !strcmp(s, "GSM-850") || !strcmp(s, "850")) return GSM_850; if(!strcmp(s, "GSM-R") || !strcmp(s, "R-GSM")) return GSM_R_900; if(!strcmp(s, "GSM900") || !strcmp(s, "GSM-900") || !strcmp(s, "900")) return GSM_900; if(!strcmp(s, "EGSM") || !strcmp(s, "E-GSM") || !strcmp(s, "EGSM900") || !strcmp(s, "E-GSM900") || !strcmp(s, "E-GSM-900")) return GSM_E_900; if(!strcmp(s, "DCS") || !strcmp(s, "DCS1800") || !strcmp(s, "DCS-1800") || !strcmp(s, "1800")) return DCS_1800; if(!strcmp(s, "PCS") || !strcmp(s, "PCS1900") || !strcmp(s, "PCS-1900") || !strcmp(s, "1900")) return PCS_1900; return -1; } double arfcn_to_freq(int n, int *bi) { if((128 <= n) && (n <= 251)) { if(bi) *bi = GSM_850; return 824.2e6 + 0.2e6 * (n - 128) + 45.0e6; } if((1 <= n) && (n <= 124)) { if(bi && (*bi != GSM_E_900)) *bi = GSM_900; return 890.0e6 + 0.2e6 * n + 45.0e6; } if(n == 0) { if(bi) *bi = GSM_E_900; return 935e6; } if((955 <= n) && (n <= 1023)) { if(bi) { if (975 <= n) *bi = GSM_E_900; else *bi = GSM_R_900; } return 890.0e6 + 0.2e6 * (n - 1024) + 45.0e6; } if((512 <= n) && (n <= 810)) { if(!bi) { fprintf(stderr, "error: ambiguous arfcn: %d\n", n); return -1.0; } if(*bi == DCS_1800) return 1710.2e6 + 0.2e6 * (n - 512) + 95.0e6; if(*bi == PCS_1900) return 1850.2e6 + 0.2e6 * (n - 512) + 80.0e6; fprintf(stderr, "error: bad (arfcn, band indicator) pair: " "(%d, %s)\n", n, bi_to_str(*bi)); return -1.0; } if((811 <= n) && (n <= 885)) { if(bi) *bi = DCS_1800; return 1710.2e6 + 0.2e6 * (n - 512) + 95.0e6; } fprintf(stderr, "error: bad arfcn: %d\n", n); return -1.0; } int freq_to_arfcn(double freq, int *bi) { if((869.2e6 <= freq) && (freq <= 893.8e6)) { if(bi) *bi = GSM_850; return (int)((freq - 869.2e6) / 0.2e6) + 128; } if((921.2e6 <= freq) && (freq <= 925.0e6)) { if(bi) *bi = GSM_R_900; return (int)((freq - 935e6) / 0.2e6) + 1024; } if((935.2e6 <= freq) && (freq <= 959.8e6)) { if(bi) *bi = GSM_900; return (int)((freq - 935e6) / 0.2e6); } if(935.0e6 == freq) { if(bi) *bi = GSM_E_900; return 0; } if((925.2e6 <= freq) && (freq <= 934.8e6)) { if(bi) *bi = GSM_E_900; return (int)((freq - 935e6) / 0.2e6) + 1024; } if((1805.2e6 <= freq) && (freq <= 1879.8e6)) { if(bi) *bi = DCS_1800; return (int)((freq - 1805.2e6) / 0.2e6) + 512; } if((1930.2e6 <= freq) && (freq <= 1989.8e6)) { if(bi) *bi = PCS_1900; return (int)((freq - 1930.2e6) / 0.2e6) + 512; } fprintf(stderr, "error: bad frequency: %lf\n", freq); return -1; } int first_chan(int bi) { switch(bi) { case GSM_850: return 128; case GSM_R_900: return 955; case GSM_900: return 1; case GSM_E_900: return 0; case DCS_1800: return 512; case PCS_1900: return 512; default: return -1; } return -1; } int next_chan_loop(int chan, int bi) { switch(bi) { case GSM_850: if((128 <= chan) && (chan < 251)) return chan + 1; if(chan == 251) return 128; return -1; case GSM_R_900: if((955 <= chan) && (chan < 974)) return chan + 1; if(chan == 974) return 955; return -1; case GSM_900: if((1 <= chan) && (chan < 124)) return chan + 1; if(chan == 124) return 1; return -1; case GSM_E_900: if((0 <= chan) && (chan < 124)) return chan + 1; if(chan == 124) return 975; if((975 <= chan) && (chan < 1023)) return chan + 1; if(chan == 1023) return 0; return -1; case DCS_1800: if((512 <= chan) && (chan < 885)) return chan + 1; if(chan == 885) return 512; return -1; case PCS_1900: if((512 <= chan) && (chan < 810)) return chan + 1; if(chan == 810) return 512; return -1; default: return -1; } return -1; } int next_chan(int chan, int bi) { switch(bi) { case GSM_850: if((128 <= chan) && (chan < 251)) return chan + 1; return -1; case GSM_R_900: if((955 <= chan) && (chan < 974)) return chan + 1; return -1; case GSM_900: if((1 <= chan) && (chan < 124)) return chan + 1; return -1; case GSM_E_900: if((0 <= chan) && (chan < 124)) return chan + 1; if(chan == 124) return 975; if((975 <= chan) && (chan < 1023)) return chan + 1; return -1; case DCS_1800: if((512 <= chan) && (chan < 885)) return chan + 1; return -1; case PCS_1900: if((512 <= chan) && (chan < 810)) return chan + 1; return -1; default: return -1; } return -1; }