Commit 25157ea1 authored by ahoms's avatar ahoms
Browse files

* added AutoLock leaveLocked method and PrevLocked init. state

* improved Frelon::Camera multi-thread locking
* added Frelon::Camera register cache on read and write commands
* force 4 channel readout on Frelon::Interface reset
* added std::map value search helpers in MiscUtils



git-svn-id: https://scm.blissgarden.org/svn/lima/trunk@157 45c4679d-1946-429d-baad-37912b19538b
parent 093650da
......@@ -66,14 +66,43 @@ class SerialLine : public HwSerialLine
int getLastWarning();
void clearCache();
void setCacheActive(bool cache_act);
void getCacheActive(bool& cache_act);
private:
enum RegOp {
None, DoCmd, ReadReg, WriteReg, DoReset, MultiRead
};
typedef std::map<Reg, std::string> RegRespMapType;
AutoMutex lock(int mode);
virtual void writeCmd(const std::string& buffer,
bool no_wait = false);
virtual void readResp(std::string& buffer,
int max_len = MaxReadLen,
double timeout = TimeoutDefault);
Espia::SerialLine& m_espia_ser_line;
Mutex m_mutex;
bool m_multi_line_cmd;
bool m_reset_cmd;
Cond m_cond;
int m_last_warn;
RegRespMapType m_reg_cache;
bool m_cache_act;
RegOp m_curr_op;
Reg m_curr_reg;
bool m_curr_cache;
std::string m_curr_resp;
std::string m_curr_fmt_resp;
};
inline AutoMutex SerialLine::lock(int mode)
{
return AutoMutex(m_cond.mutex(), mode);
}
} // namespace Frelon
......
......@@ -66,6 +66,10 @@ class SerialLine : HwSerialLine
int getLastWarning();
void clearCache();
void setCacheActive(bool cache_act);
void getCacheActive(bool& cache_act /Out/);
};
......
......@@ -73,6 +73,8 @@ static const MLCmdPair MLCmdStrCList[] = {
MLCmdPair(Dac, "D"),
MLCmdPair(Volt, "V"),
MLCmdPair(Aoi, "AOI"),
MLCmdPair(Aoi, "PLL"),
MLCmdPair(Aoi, "TIM"),
};
MultiLineCmdStrMapType
lima::Frelon::MultiLineCmdStrMap(C_LIST_ITERS(MLCmdStrCList));
......
......@@ -339,6 +339,7 @@ void Interface::reset(ResetLevel reset_level)
m_cam.hardReset();
m_cam.setFrameTransferMode(FFM);
m_cam.setInputChan(Chan1234);
m_sync.setNbFrames(1);
m_sync.setExpTime(1.0);
......
......@@ -19,10 +19,12 @@ SerialLine::SerialLine(Espia::SerialLine& espia_ser_line)
m_espia_ser_line.setLineTerm("\r\n");
m_espia_ser_line.setTimeout(TimeoutNormal);
m_multi_line_cmd = false;
m_reset_cmd = false;
m_last_warn = 0;
m_curr_op = None;
m_curr_cache = false;
m_cache_act = true;
flush();
}
......@@ -32,28 +34,64 @@ Espia::SerialLine& SerialLine::getEspiaSerialLine()
}
void SerialLine::write(const string& buffer, bool no_wait)
{
AutoMutex l = lock(AutoMutex::Locked);
while (m_curr_op != None)
m_cond.wait();
writeCmd(buffer, no_wait);
l.leaveLocked();
}
void SerialLine::writeCmd(const string& buffer, bool no_wait)
{
MsgPartStrMapType msg_parts;
splitMsg(buffer, msg_parts);
const string& cmd = msg_parts[MsgCmd];
m_mutex.lock();
m_multi_line_cmd = false;
m_reset_cmd = (cmd == CmdStrMap[Reset]);
if (!m_reset_cmd) {
if (cmd == CmdStrMap[Reset]) {
m_curr_op = DoReset;
m_reg_cache.clear();
} else {
MultiLineCmdStrMapType::const_iterator it, end;
end = MultiLineCmdStrMap.end();
for (it = MultiLineCmdStrMap.begin(); it != end; ++it) {
if (it->second == cmd) {
m_multi_line_cmd = true;
break;
}
it = FindMapValue(MultiLineCmdStrMap, cmd);
if (it != end)
m_curr_op = MultiRead;
}
bool reg_found = false;
if (m_curr_op == None) {
RegStrMapType::const_iterator it, end = RegStrMap.end();
it = FindMapValue(RegStrMap, cmd);
reg_found = (it != end);
if (reg_found)
m_curr_reg = it->first;
}
m_curr_cache = false;
if (m_cache_act && reg_found && (m_curr_reg != Warn)) {
bool is_req = !msg_parts[MsgReq].empty();
m_curr_op = is_req ? ReadReg : WriteReg;
const string& cache_val = m_reg_cache[m_curr_reg];
if (is_req) {
m_curr_resp = cache_val;
m_curr_cache = !m_curr_resp.empty();
} else {
m_curr_resp = msg_parts[MsgVal];
m_curr_cache = (m_curr_resp == cache_val);
}
if (m_curr_cache)
return;
}
string sync = !msg_parts[MsgSync].size() ? ">" : "";
string term = !msg_parts[MsgTerm].size() ? "\r\n" : "";
if (m_curr_op == None)
m_curr_op = DoCmd;
string sync = msg_parts[MsgSync].empty() ? ">" : "";
string term = msg_parts[MsgTerm].empty() ? "\r\n" : "";
string msg = sync + buffer + term;
m_espia_ser_line.write(msg, no_wait);
......@@ -72,27 +110,51 @@ void SerialLine::readStr(string& buffer, int max_len,
void SerialLine::readLine(string& buffer, int max_len, double timeout)
{
class AutoUnlock
{
Mutex& m;
public:
AutoUnlock(Mutex& mutex) : m(mutex) {}
~AutoUnlock() { m.unlock(); }
} ul(m_mutex);
AutoMutex l = lock(AutoMutex::PrevLocked);
if ((timeout == TimeoutDefault) && (m_multi_line_cmd))
readResp(buffer, max_len, timeout);
}
void SerialLine::readResp(string& buffer, int max_len, double timeout)
{
if (m_curr_op == None)
throw LIMA_HW_EXC(Error, "readLine without previous write");
if ((m_curr_op == MultiRead) && (timeout == TimeoutDefault))
readMultiLine(buffer, max_len);
else
readSingleLine(buffer, max_len, timeout);
m_curr_op = None;
m_cond.signal();
}
void SerialLine::readSingleLine(string& buffer, int max_len, double timeout)
{
if ((timeout == TimeoutDefault) && (m_reset_cmd)) {
timeout = TimeoutReset;
m_reset_cmd = false;
bool is_req = (m_curr_op == ReadReg);
if (m_curr_cache) {
ostringstream os;
os << "!OK";
if (is_req)
os << ":" << m_curr_resp;
os << "\r\n";
buffer = os.str();
m_curr_fmt_resp = m_curr_resp;
return;
}
if ((m_curr_op == DoReset) && (timeout == TimeoutDefault))
timeout = TimeoutReset;
m_espia_ser_line.readLine(buffer, max_len, timeout);
decodeFmtResp(buffer, m_curr_fmt_resp);
bool reg_op = ((m_curr_op == WriteReg) || (m_curr_op == ReadReg));
if (!m_cache_act || !reg_op || (m_curr_reg == Warn))
return;
string& cache_val = m_reg_cache[m_curr_reg];
cache_val = is_req ? m_curr_fmt_resp : m_curr_resp;
}
void SerialLine::readMultiLine(string& buffer, int max_len)
......@@ -199,10 +261,15 @@ void SerialLine::decodeFmtResp(const string& ans, string& fmt_resp)
void SerialLine::sendFmtCmd(const string& cmd, string& resp)
{
write(cmd);
AutoMutex l = lock(AutoMutex::Locked);
m_curr_fmt_resp.clear();
writeCmd(cmd);
string ans;
readLine(ans);
decodeFmtResp(ans, resp);
readResp(ans);
resp = m_curr_fmt_resp;
}
int SerialLine::getLastWarning()
......@@ -211,3 +278,23 @@ int SerialLine::getLastWarning()
m_last_warn = 0;
return last_warn;
}
void SerialLine::clearCache()
{
AutoMutex l = lock(AutoMutex::Locked);
m_reg_cache.clear();
}
void SerialLine::setCacheActive(bool cache_act)
{
AutoMutex l = lock(AutoMutex::Locked);
if (cache_act && !m_cache_act)
m_reg_cache.clear();
m_cache_act = cache_act;
}
void SerialLine::getCacheActive(bool& cache_act)
{
AutoMutex l = lock(AutoMutex::Locked);
cache_act = m_cache_act;
}
......@@ -36,7 +36,7 @@ template <class M>
class AutoLock
{
public:
enum { UnLocked, Locked, TryLocked };
enum { UnLocked, Locked, TryLocked, PrevLocked };
AutoLock(M& mutex, int state=Locked)
{ d = new AutoLockData(mutex, state); }
......@@ -62,23 +62,27 @@ public:
bool locked() const
{ return d->locked(); }
void leaveLocked()
{ d->leaveLocked(); }
private:
class AutoLockData
{
public:
AutoLockData(M& mutex, int state=Locked)
: m(mutex), l(false)
: m(mutex), l(false), ul_at_end(true)
{
switch (state) {
case Locked: lock(); break;
case TryLocked: tryLock(); break;
case Locked: lock(); break;
case TryLocked: tryLock(); break;
case PrevLocked: l = true; break;
default: break;
}
}
~AutoLockData()
{
if (l)
if (l && ul_at_end)
unlock();
}
......@@ -111,6 +115,11 @@ private:
return l;
}
void leaveLocked()
{
ul_at_end = false;
}
M& mutex() const
{ return m; }
......@@ -121,6 +130,7 @@ private:
AutoCounter c;
M& m;
bool l;
bool ul_at_end;
};
AutoLockData *getData() const
......
#ifndef MISCUTILS_H
#define MISCUTILS_H
#include <map>
namespace lima
{
......@@ -8,6 +10,28 @@ namespace lima
#define C_LIST_END(list) ((list) + C_LIST_SIZE(list))
#define C_LIST_ITERS(list) list, C_LIST_END(list)
// Map search helpers
template <class V>
class SecondIs
{
public:
SecondIs(V v) : m_val(v)
{}
template <class K>
bool operator () (const std::pair<K, V>& p)
{ return (p.second == m_val); }
private:
V m_val;
};
template <class M, class V>
typename M::const_iterator FindMapValue(const M& m, V v)
{
return find_if(m.begin(), m.end(), SecondIs<V>(v));
}
} // namespace lima
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment